GDB (API)
/home/stan/gdb/src/gdb/gdb-gdb.py
Go to the documentation of this file.
00001 # Copyright (C) 2009-2013 Free Software Foundation, Inc.
00002 #
00003 # This file is part of GDB.
00004 #
00005 # This program is free software; you can redistribute it and/or modify
00006 # it under the terms of the GNU General Public License as published by
00007 # the Free Software Foundation; either version 3 of the License, or
00008 # (at your option) any later version.
00009 #
00010 # This program is distributed in the hope that it will be useful,
00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 # GNU General Public License for more details.
00014 #
00015 # You should have received a copy of the GNU General Public License
00016 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 import gdb
00019 import os.path
00020 
00021 class TypeFlag:
00022     """A class that allows us to store a flag name, its short name,
00023     and its value.
00024 
00025     In the GDB sources, struct type has a component called instance_flags
00026     in which the value is the addition of various flags.  These flags are
00027     defined by two enumerates: type_flag_value, and type_instance_flag_value.
00028     This class helps us recreate a list with all these flags that is
00029     easy to manipulate and sort.  Because all flag names start with either
00030     TYPE_FLAG_ or TYPE_INSTANCE_FLAG_, a short_name attribute is provided
00031     that strips this prefix.
00032 
00033     ATTRIBUTES
00034       name:  The enumeration name (eg: "TYPE_FLAG_UNSIGNED").
00035       value: The associated value.
00036       short_name: The enumeration name, with the suffix stripped.
00037     """
00038     def __init__(self, name, value):
00039         self.name = name
00040         self.value = value
00041         self.short_name = name.replace("TYPE_FLAG_", '')
00042         if self.short_name == name:
00043             self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
00044     def __cmp__(self, other):
00045         """Sort by value order."""
00046         return self.value.__cmp__(other.value)
00047 
00048 # A list of all existing TYPE_FLAGS_* and TYPE_INSTANCE_FLAGS_*
00049 # enumerations, stored as TypeFlags objects.  Lazy-initialized.
00050 TYPE_FLAGS = None
00051 
00052 class TypeFlagsPrinter:
00053     """A class that prints a decoded form of an instance_flags value.
00054 
00055     This class uses a global named TYPE_FLAGS, which is a list of
00056     all defined TypeFlag values.  Using a global allows us to compute
00057     this list only once.
00058 
00059     This class relies on a couple of enumeration types being defined.
00060     If not, then printing of the instance_flag is going to be degraded,
00061     but it's not a fatal error.
00062     """
00063     def __init__(self, val):
00064         self.val = val
00065     def __str__(self):
00066         global TYPE_FLAGS
00067         if TYPE_FLAGS is None:
00068             self.init_TYPE_FLAGS()
00069         if not self.val:
00070             return "0"
00071         if TYPE_FLAGS:
00072             flag_list = [flag.short_name for flag in TYPE_FLAGS
00073                          if self.val & flag.value]
00074         else:
00075             flag_list = ["???"]
00076         return "0x%x [%s]" % (self.val, "|".join(flag_list))
00077     def init_TYPE_FLAGS(self):
00078         """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
00079         This operation requires the search of a couple of enumeration types.
00080         If not found, a warning is printed on stdout, and TYPE_FLAGS is
00081         set to the empty list.
00082 
00083         The resulting list is sorted by increasing value, to facilitate
00084         printing of the list of flags used in an instance_flags value.
00085         """
00086         global TYPE_FLAGS
00087         TYPE_FLAGS = []
00088         try:
00089             flags = gdb.lookup_type("enum type_flag_value")
00090         except:
00091             print "Warning: Cannot find enum type_flag_value type."
00092             print "         `struct type' pretty-printer will be degraded"
00093             return
00094         try:
00095             iflags = gdb.lookup_type("enum type_instance_flag_value")
00096         except:
00097             print "Warning: Cannot find enum type_instance_flag_value type."
00098             print "         `struct type' pretty-printer will be degraded"
00099             return
00100         # Note: TYPE_FLAG_MIN is a duplicate of TYPE_FLAG_UNSIGNED,
00101         # so exclude it from the list we are building.
00102         TYPE_FLAGS = [TypeFlag(field.name, field.enumval)
00103                       for field in flags.fields()
00104                       if field.name != 'TYPE_FLAG_MIN']
00105         TYPE_FLAGS += [TypeFlag(field.name, field.enumval)
00106                        for field in iflags.fields()]
00107         TYPE_FLAGS.sort()
00108 
00109 class StructTypePrettyPrinter:
00110     """Pretty-print an object of type struct type"""
00111     def __init__(self, val):
00112         self.val = val
00113     def to_string(self):
00114         fields = []
00115         fields.append("pointer_type = %s" % self.val['pointer_type'])
00116         fields.append("reference_type = %s" % self.val['reference_type'])
00117         fields.append("chain = %s" % self.val['reference_type'])
00118         fields.append("instance_flags = %s"
00119                       % TypeFlagsPrinter(self.val['instance_flags']))
00120         fields.append("length = %d" % self.val['length'])
00121         fields.append("main_type = %s" % self.val['main_type'])
00122         return "\n{" + ",\n ".join(fields) + "}"
00123 
00124 class StructMainTypePrettyPrinter:
00125     """Pretty-print an objet of type main_type"""
00126     def __init__(self, val):
00127         self.val = val
00128     def flags_to_string(self):
00129         """struct main_type contains a series of components that
00130         are one-bit ints whose name start with "flag_".  For instance:
00131         flag_unsigned, flag_stub, etc.  In essence, these components are
00132         really boolean flags, and this method prints a short synthetic
00133         version of the value of all these flags.  For instance, if
00134         flag_unsigned and flag_static are the only components set to 1,
00135         this function will return "unsigned|static".
00136         """
00137         fields = [field.name.replace("flag_", "")
00138                   for field in self.val.type.fields()
00139                   if field.name.startswith("flag_")
00140                      and self.val[field.name]]
00141         return "|".join(fields)
00142     def owner_to_string(self):
00143         """Return an image of component "owner".
00144         """
00145         if self.val['flag_objfile_owned'] != 0:
00146             return "%s (objfile)" % self.val['owner']['objfile']
00147         else:
00148             return "%s (gdbarch)" % self.val['owner']['gdbarch']
00149     def struct_field_location_img(self, field_val):
00150         """Return an image of the loc component inside the given field
00151         gdb.Value.
00152         """
00153         loc_val = field_val['loc']
00154         loc_kind = str(field_val['loc_kind'])
00155         if loc_kind == "FIELD_LOC_KIND_BITPOS":
00156             return 'bitpos = %d' % loc_val['bitpos']
00157         elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
00158             return 'enumval = %d' % loc_val['enumval']
00159         elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
00160             return 'physaddr = 0x%x' % loc_val['physaddr']
00161         elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
00162             return 'physname = %s' % loc_val['physname']
00163         elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
00164             return 'dwarf_block = %s' % loc_val['dwarf_block']
00165         else:
00166             return 'loc = ??? (unsupported loc_kind value)'
00167     def struct_field_img(self, fieldno):
00168         """Return an image of the main_type field number FIELDNO.
00169         """
00170         f = self.val['flds_bnds']['fields'][fieldno]
00171         label = "flds_bnds.fields[%d]:" % fieldno
00172         if f['artificial']:
00173             label += " (artificial)"
00174         fields = []
00175         fields.append("name = %s" % f['name'])
00176         fields.append("type = %s" % f['type'])
00177         fields.append("loc_kind = %s" % f['loc_kind'])
00178         fields.append("bitsize = %d" % f['bitsize'])
00179         fields.append(self.struct_field_location_img(f))
00180         return label + "\n" + "  {" + ",\n   ".join(fields) + "}"
00181     def bounds_img(self):
00182         """Return an image of the main_type bounds.
00183         """
00184         b = self.val['flds_bnds']['bounds'].dereference()
00185         low = str(b['low'])
00186         if b['low_undefined'] != 0:
00187             low += " (undefined)"
00188         high = str(b['high'])
00189         if b['high_undefined'] != 0:
00190             high += " (undefined)"
00191         return "flds_bnds.bounds = {%s, %s}" % (low, high)
00192     def type_specific_img(self):
00193         """Return a string image of the main_type type_specific union.
00194         Only the relevant component of that union is printed (based on
00195         the value of the type_specific_kind field.
00196         """
00197         type_specific_kind = str(self.val['type_specific_field'])
00198         type_specific = self.val['type_specific']
00199         if type_specific_kind == "TYPE_SPECIFIC_NONE":
00200             img = 'type_specific_field = %s' % type_specific_kind
00201         elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
00202             img = "cplus_stuff = %s" % type_specific['cplus_stuff']
00203         elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
00204             img = ("gnat_stuff = {descriptive_type = %s}"
00205                    % type_specific['gnat_stuff']['descriptive_type'])
00206         elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
00207             img = "floatformat[0..1] = %s" % type_specific['floatformat']
00208         elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
00209             img = ("calling_convention = %d"
00210                    % type_specific['func_stuff']['calling_convention'])
00211             # tail_call_list is not printed.
00212         else:
00213             img = ("type_specific = ??? (unknown type_secific_kind: %s)"
00214                    % type_specific_kind)
00215         return img
00216 
00217     def to_string(self):
00218         """Return a pretty-printed image of our main_type.
00219         """
00220         fields = []
00221         fields.append("name = %s" % self.val['name'])
00222         fields.append("tag_name = %s" % self.val['tag_name'])
00223         fields.append("code = %s" % self.val['code'])
00224         fields.append("flags = [%s]" % self.flags_to_string())
00225         fields.append("owner = %s" % self.owner_to_string())
00226         fields.append("target_type = %s" % self.val['target_type'])
00227         fields.append("vptr_basetype = %s" % self.val['vptr_basetype'])
00228         if self.val['nfields'] > 0:
00229             for fieldno in range(self.val['nfields']):
00230                 fields.append(self.struct_field_img(fieldno))
00231         if self.val['code'] == gdb.TYPE_CODE_RANGE:
00232             fields.append(self.bounds_img())
00233         fields.append(self.type_specific_img())
00234 
00235         return "\n{" + ",\n ".join(fields) + "}"
00236 
00237 def type_lookup_function(val):
00238     """A routine that returns the correct pretty printer for VAL
00239     if appropriate.  Returns None otherwise.
00240     """
00241     if val.type.tag == "type":
00242         return StructTypePrettyPrinter(val)
00243     elif val.type.tag == "main_type":
00244         return StructMainTypePrettyPrinter(val)
00245     return None
00246 
00247 def register_pretty_printer(objfile):
00248     """A routine to register a pretty-printer against the given OBJFILE.
00249     """
00250     objfile.pretty_printers.append(type_lookup_function)
00251 
00252 if __name__ == "__main__":
00253     if gdb.current_objfile() is not None:
00254         # This is the case where this script is being "auto-loaded"
00255         # for a given objfile.  Register the pretty-printer for that
00256         # objfile.
00257         register_pretty_printer(gdb.current_objfile())
00258     else:
00259         # We need to locate the objfile corresponding to the GDB
00260         # executable, and register the pretty-printer for that objfile.
00261         # FIXME: The condition used to match the objfile is too simplistic
00262         # and will not work on Windows.
00263         for objfile in gdb.objfiles():
00264             if os.path.basename(objfile.filename) == "gdb":
00265                 objfile.pretty_printers.append(type_lookup_function)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines