gdb/gdb-gdb.py - gdb

Global variables defined

Functions defined

Source code

  1. # Copyright (C) 2009-2015 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. import gdb
  18. import os.path

  19. class TypeFlag:
  20.     """A class that allows us to store a flag name, its short name,
  21.     and its value.

  22.     In the GDB sources, struct type has a component called instance_flags
  23.     in which the value is the addition of various flags.  These flags are
  24.     defined by two enumerates: type_flag_value, and type_instance_flag_value.
  25.     This class helps us recreate a list with all these flags that is
  26.     easy to manipulate and sort.  Because all flag names start with either
  27.     TYPE_FLAG_ or TYPE_INSTANCE_FLAG_, a short_name attribute is provided
  28.     that strips this prefix.

  29.     ATTRIBUTES
  30.       name:  The enumeration name (eg: "TYPE_FLAG_UNSIGNED").
  31.       value: The associated value.
  32.       short_name: The enumeration name, with the suffix stripped.
  33.     """
  34.     def __init__(self, name, value):
  35.         self.name = name
  36.         self.value = value
  37.         self.short_name = name.replace("TYPE_FLAG_", '')
  38.         if self.short_name == name:
  39.             self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
  40.     def __cmp__(self, other):
  41.         """Sort by value order."""
  42.         return self.value.__cmp__(other.value)

  43. # A list of all existing TYPE_FLAGS_* and TYPE_INSTANCE_FLAGS_*
  44. # enumerations, stored as TypeFlags objects.  Lazy-initialized.
  45. TYPE_FLAGS = None

  46. class TypeFlagsPrinter:
  47.     """A class that prints a decoded form of an instance_flags value.

  48.     This class uses a global named TYPE_FLAGS, which is a list of
  49.     all defined TypeFlag values.  Using a global allows us to compute
  50.     this list only once.

  51.     This class relies on a couple of enumeration types being defined.
  52.     If not, then printing of the instance_flag is going to be degraded,
  53.     but it's not a fatal error.
  54.     """
  55.     def __init__(self, val):
  56.         self.val = val
  57.     def __str__(self):
  58.         global TYPE_FLAGS
  59.         if TYPE_FLAGS is None:
  60.             self.init_TYPE_FLAGS()
  61.         if not self.val:
  62.             return "0"
  63.         if TYPE_FLAGS:
  64.             flag_list = [flag.short_name for flag in TYPE_FLAGS
  65.                          if self.val & flag.value]
  66.         else:
  67.             flag_list = ["???"]
  68.         return "0x%x [%s]" % (self.val, "|".join(flag_list))
  69.     def init_TYPE_FLAGS(self):
  70.         """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
  71.         This operation requires the search of a couple of enumeration types.
  72.         If not found, a warning is printed on stdout, and TYPE_FLAGS is
  73.         set to the empty list.

  74.         The resulting list is sorted by increasing value, to facilitate
  75.         printing of the list of flags used in an instance_flags value.
  76.         """
  77.         global TYPE_FLAGS
  78.         TYPE_FLAGS = []
  79.         try:
  80.             flags = gdb.lookup_type("enum type_flag_value")
  81.         except:
  82.             print "Warning: Cannot find enum type_flag_value type."
  83.             print "         `struct type' pretty-printer will be degraded"
  84.             return
  85.         try:
  86.             iflags = gdb.lookup_type("enum type_instance_flag_value")
  87.         except:
  88.             print "Warning: Cannot find enum type_instance_flag_value type."
  89.             print "         `struct type' pretty-printer will be degraded"
  90.             return
  91.         # Note: TYPE_FLAG_MIN is a duplicate of TYPE_FLAG_UNSIGNED,
  92.         # so exclude it from the list we are building.
  93.         TYPE_FLAGS = [TypeFlag(field.name, field.enumval)
  94.                       for field in flags.fields()
  95.                       if field.name != 'TYPE_FLAG_MIN']
  96.         TYPE_FLAGS += [TypeFlag(field.name, field.enumval)
  97.                        for field in iflags.fields()]
  98.         TYPE_FLAGS.sort()

  99. class StructTypePrettyPrinter:
  100.     """Pretty-print an object of type struct type"""
  101.     def __init__(self, val):
  102.         self.val = val
  103.     def to_string(self):
  104.         fields = []
  105.         fields.append("pointer_type = %s" % self.val['pointer_type'])
  106.         fields.append("reference_type = %s" % self.val['reference_type'])
  107.         fields.append("chain = %s" % self.val['reference_type'])
  108.         fields.append("instance_flags = %s"
  109.                       % TypeFlagsPrinter(self.val['instance_flags']))
  110.         fields.append("length = %d" % self.val['length'])
  111.         fields.append("main_type = %s" % self.val['main_type'])
  112.         return "\n{" + ",\n ".join(fields) + "}"

  113. class StructMainTypePrettyPrinter:
  114.     """Pretty-print an objet of type main_type"""
  115.     def __init__(self, val):
  116.         self.val = val
  117.     def flags_to_string(self):
  118.         """struct main_type contains a series of components that
  119.         are one-bit ints whose name start with "flag_".  For instance:
  120.         flag_unsigned, flag_stub, etc.  In essence, these components are
  121.         really boolean flags, and this method prints a short synthetic
  122.         version of the value of all these flags.  For instance, if
  123.         flag_unsigned and flag_static are the only components set to 1,
  124.         this function will return "unsigned|static".
  125.         """
  126.         fields = [field.name.replace("flag_", "")
  127.                   for field in self.val.type.fields()
  128.                   if field.name.startswith("flag_")
  129.                      and self.val[field.name]]
  130.         return "|".join(fields)
  131.     def owner_to_string(self):
  132.         """Return an image of component "owner".
  133.         """
  134.         if self.val['flag_objfile_owned'] != 0:
  135.             return "%s (objfile)" % self.val['owner']['objfile']
  136.         else:
  137.             return "%s (gdbarch)" % self.val['owner']['gdbarch']
  138.     def struct_field_location_img(self, field_val):
  139.         """Return an image of the loc component inside the given field
  140.         gdb.Value.
  141.         """
  142.         loc_val = field_val['loc']
  143.         loc_kind = str(field_val['loc_kind'])
  144.         if loc_kind == "FIELD_LOC_KIND_BITPOS":
  145.             return 'bitpos = %d' % loc_val['bitpos']
  146.         elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
  147.             return 'enumval = %d' % loc_val['enumval']
  148.         elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
  149.             return 'physaddr = 0x%x' % loc_val['physaddr']
  150.         elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
  151.             return 'physname = %s' % loc_val['physname']
  152.         elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
  153.             return 'dwarf_block = %s' % loc_val['dwarf_block']
  154.         else:
  155.             return 'loc = ??? (unsupported loc_kind value)'
  156.     def struct_field_img(self, fieldno):
  157.         """Return an image of the main_type field number FIELDNO.
  158.         """
  159.         f = self.val['flds_bnds']['fields'][fieldno]
  160.         label = "flds_bnds.fields[%d]:" % fieldno
  161.         if f['artificial']:
  162.             label += " (artificial)"
  163.         fields = []
  164.         fields.append("name = %s" % f['name'])
  165.         fields.append("type = %s" % f['type'])
  166.         fields.append("loc_kind = %s" % f['loc_kind'])
  167.         fields.append("bitsize = %d" % f['bitsize'])
  168.         fields.append(self.struct_field_location_img(f))
  169.         return label + "\n" + "  {" + ",\n   ".join(fields) + "}"
  170.     def bounds_img(self):
  171.         """Return an image of the main_type bounds.
  172.         """
  173.         b = self.val['flds_bnds']['bounds'].dereference()
  174.         low = str(b['low'])
  175.         if b['low_undefined'] != 0:
  176.             low += " (undefined)"
  177.         high = str(b['high'])
  178.         if b['high_undefined'] != 0:
  179.             high += " (undefined)"
  180.         return "flds_bnds.bounds = {%s, %s}" % (low, high)
  181.     def type_specific_img(self):
  182.         """Return a string image of the main_type type_specific union.
  183.         Only the relevant component of that union is printed (based on
  184.         the value of the type_specific_kind field.
  185.         """
  186.         type_specific_kind = str(self.val['type_specific_field'])
  187.         type_specific = self.val['type_specific']
  188.         if type_specific_kind == "TYPE_SPECIFIC_NONE":
  189.             img = 'type_specific_field = %s' % type_specific_kind
  190.         elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
  191.             img = "cplus_stuff = %s" % type_specific['cplus_stuff']
  192.         elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
  193.             img = ("gnat_stuff = {descriptive_type = %s}"
  194.                    % type_specific['gnat_stuff']['descriptive_type'])
  195.         elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
  196.             img = "floatformat[0..1] = %s" % type_specific['floatformat']
  197.         elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
  198.             img = ("calling_convention = %d"
  199.                    % type_specific['func_stuff']['calling_convention'])
  200.             # tail_call_list is not printed.
  201.         else:
  202.             img = ("type_specific = ??? (unknown type_secific_kind: %s)"
  203.                    % type_specific_kind)
  204.         return img

  205.     def to_string(self):
  206.         """Return a pretty-printed image of our main_type.
  207.         """
  208.         fields = []
  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.         fields.append("vptr_basetype = %s" % self.val['vptr_basetype'])
  216.         if self.val['nfields'] > 0:
  217.             for fieldno in range(self.val['nfields']):
  218.                 fields.append(self.struct_field_img(fieldno))
  219.         if self.val['code'] == gdb.TYPE_CODE_RANGE:
  220.             fields.append(self.bounds_img())
  221.         fields.append(self.type_specific_img())

  222.         return "\n{" + ",\n ".join(fields) + "}"

  223. def type_lookup_function(val):
  224.     """A routine that returns the correct pretty printer for VAL
  225.     if appropriate.  Returns None otherwise.
  226.     """
  227.     if val.type.tag == "type":
  228.         return StructTypePrettyPrinter(val)
  229.     elif val.type.tag == "main_type":
  230.         return StructMainTypePrettyPrinter(val)
  231.     return None

  232. def register_pretty_printer(objfile):
  233.     """A routine to register a pretty-printer against the given OBJFILE.
  234.     """
  235.     objfile.pretty_printers.append(type_lookup_function)

  236. if __name__ == "__main__":
  237.     if gdb.current_objfile() is not None:
  238.         # This is the case where this script is being "auto-loaded"
  239.         # for a given objfile.  Register the pretty-printer for that
  240.         # objfile.
  241.         register_pretty_printer(gdb.current_objfile())
  242.     else:
  243.         # We need to locate the objfile corresponding to the GDB
  244.         # executable, and register the pretty-printer for that objfile.
  245.         # FIXME: The condition used to match the objfile is too simplistic
  246.         # and will not work on Windows.
  247.         for objfile in gdb.objfiles():
  248.             if os.path.basename(objfile.filename) == "gdb":
  249.                 objfile.pretty_printers.append(type_lookup_function)