Copy gdb-gdb.py to build dir
authorSimon Marchi <simon.marchi@ericsson.com>
Wed, 27 Jun 2018 18:32:02 +0000 (14:32 -0400)
committerSimon Marchi <simon.marchi@ericsson.com>
Wed, 27 Jun 2018 18:32:02 +0000 (14:32 -0400)
I have thought for a long time how nice it would be to have cool pretty
printers for GDB's internal types.  Well, turns out there are few
already in gdb-gdb.py!  Unfortunately, if you build GDB outside of the
source directory, that file never gets loaded.  top-gdb will look for a
file called

  ../path/to/build/gdb/gdb-gdb.py

but that file is in the source directory at

  ../path/to/src/gdb/gdb-gdb.py

This patch makes it so we copy it to the build directory, just like we
do for gdb-gdb.gdb.  With this, I can at least see the file getting
automatically loaded:

(top-gdb) info pretty-printer
global pretty-printers:
  builtin
    mpx_bound128
  objfile /home/emaisin/build/binutils-gdb/gdb/gdb pretty-printers:
  type_lookup_function

I noticed that running "make" didn't re-generate gdb-gdb.py from
gdb-gdb.py.in.  That's because it's copied when running the configure
script and that's it.  I added a rule in the Makefile for that (and for
gdb-gdb.gdb too) and added them as a dependency to the "all" target.

gdb/ChangeLog:

* gdb-gdb.py: Move to...
* gdb-gdb.py.in: ... here.
* configure.ac (AC_CONFIG_FILES): Add gdb-gdb.py.
* Makefile.in (all): Add gdb-gdb.gdb and gdb-gdb.py as
dependencies.
(distclean): Remove gdb-gdb.py when cleaning.
(gdb-gdb.py, gdb-gdb.gdb): New rules.
* configure: Re-generate.

gdb/ChangeLog
gdb/Makefile.in
gdb/configure
gdb/configure.ac
gdb/gdb-gdb.py [deleted file]
gdb/gdb-gdb.py.in [new file with mode: 0644]

index c791add2b396065fb8fd0c08ec2f70ba47616b7e..644aed8e7519e2ad70a82ba66c3eba40ad588f0a 100644 (file)
@@ -1,3 +1,14 @@
+2018-06-27  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * gdb-gdb.py: Move to...
+       * gdb-gdb.py.in: ... here.
+       * configure.ac (AC_CONFIG_FILES): Add gdb-gdb.py.
+       * Makefile.in (all): Add gdb-gdb.gdb and gdb-gdb.py as
+       dependencies.
+       (distclean): Remove gdb-gdb.py when cleaning.
+       (gdb-gdb.py, gdb-gdb.gdb): New rules.
+       * configure: Re-generate.
+
 2018-06-27  Pedro Alves  <palves@redhat.com>
 
        * proc-service.c (get_ps_regcache): New.
index 354a6361b76ca629c57462261c79b44dc11fa7d8..5934cd6a23e5f3213ecb8af4cfae0c892e19fdf4 100644 (file)
@@ -1607,7 +1607,7 @@ generated_files = \
 # Flags needed to compile Python code
 PYTHON_CFLAGS = @PYTHON_CFLAGS@
 
-all: gdb$(EXEEXT) $(CONFIG_ALL)
+all: gdb$(EXEEXT) $(CONFIG_ALL) gdb-gdb.py gdb-gdb.gdb
        @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do
 
 # Rule for compiling .c files in the top-level gdb directory.
@@ -1983,7 +1983,8 @@ distclean: clean
        rm -f gdbserver/config.status gdbserver/config.log
        rm -f gdbserver/tm.h gdbserver/xm.h gdbserver/nm.h
        rm -f gdbserver/Makefile gdbserver/config.cache
-       rm -f nm.h config.status config.h stamp-h gdb-gdb.gdb jit-reader.h
+       rm -f nm.h config.status config.h stamp-h b jit-reader.h
+       rm -f gdb-gdb.py gdb-gdb.gdb
        rm -f y.output yacc.acts yacc.tmp y.tab.h
        rm -f config.log config.cache
        rm -f Makefile
@@ -2060,6 +2061,12 @@ jit-reader.h: $(srcdir)/jit-reader.in
 gcore: $(srcdir)/gcore.in
        $(SHELL) config.status $@
 
+gdb-gdb.py: $(srcdir)/gdb-gdb.py.in
+       $(SHELL) config.status $@
+
+gdb-gdb.gdb: $(srcdir)/gdb-gdb.gdb.in
+       $(SHELL) config.status $@
+
 config.h: stamp-h ; @true
 stamp-h: $(srcdir)/config.in config.status
        CONFIG_HEADERS=config.h:config.in \
index 24e89682d27f305a6d3c0685cb77f6796a89debd..d3a3bbe44c9dae16614e7136b9a7623c9c9dcbb3 100755 (executable)
@@ -17789,7 +17789,7 @@ fi
 
 ac_config_files="$ac_config_files gcore"
 
-ac_config_files="$ac_config_files Makefile gdb-gdb.gdb doc/Makefile data-directory/Makefile"
+ac_config_files="$ac_config_files Makefile gdb-gdb.gdb gdb-gdb.py doc/Makefile data-directory/Makefile"
 
 
 cat >confcache <<\_ACEOF
@@ -18516,6 +18516,7 @@ do
     "gcore") CONFIG_FILES="$CONFIG_FILES gcore" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "gdb-gdb.gdb") CONFIG_FILES="$CONFIG_FILES gdb-gdb.gdb" ;;
+    "gdb-gdb.py") CONFIG_FILES="$CONFIG_FILES gdb-gdb.py" ;;
     "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
     "data-directory/Makefile") CONFIG_FILES="$CONFIG_FILES data-directory/Makefile" ;;
 
@@ -19156,6 +19157,12 @@ esac
 case x$CONFIG_HEADERS in
 xconfig.h:config.in)
 echo > stamp-h ;;
+esac
+ ;;
+    "gdb-gdb.py":F)
+case x$CONFIG_HEADERS in
+xconfig.h:config.in)
+echo > stamp-h ;;
 esac
  ;;
     "doc/Makefile":F)
index aa22d1d9d36356d1078694d5a9464e05406e9388..44b6c62d70959d90ec7aa1672cf4558d675f205d 100644 (file)
@@ -2305,7 +2305,7 @@ fi
 GDB_AC_TRANSFORM([gdb], [GDB_TRANSFORM_NAME])
 GDB_AC_TRANSFORM([gcore], [GCORE_TRANSFORM_NAME])
 AC_CONFIG_FILES([gcore], [chmod +x gcore])
-AC_CONFIG_FILES([Makefile gdb-gdb.gdb doc/Makefile data-directory/Makefile],
+AC_CONFIG_FILES([Makefile gdb-gdb.gdb gdb-gdb.py doc/Makefile data-directory/Makefile],
 [
 case x$CONFIG_HEADERS in
 xconfig.h:config.in)
diff --git a/gdb/gdb-gdb.py b/gdb/gdb-gdb.py
deleted file mode 100644 (file)
index b8bb1ad..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-# Copyright (C) 2009-2018 Free Software Foundation, Inc.
-#
-# This file is part of GDB.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import gdb
-import os.path
-
-class TypeFlag:
-    """A class that allows us to store a flag name, its short name,
-    and its value.
-
-    In the GDB sources, struct type has a component called instance_flags
-    in which the value is the addition of various flags.  These flags are
-    defined by the enumerates type_instance_flag_value.  This class helps us
-    recreate a list with all these flags that is easy to manipulate and sort.
-    Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
-    attribute is provided that strips this prefix.
-
-    ATTRIBUTES
-      name:  The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
-      value: The associated value.
-      short_name: The enumeration name, with the suffix stripped.
-    """
-    def __init__(self, name, value):
-        self.name = name
-        self.value = value
-        self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
-    def __cmp__(self, other):
-        """Sort by value order."""
-        return self.value.__cmp__(other.value)
-
-# A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
-# stored as TypeFlags objects.  Lazy-initialized.
-TYPE_FLAGS = None
-
-class TypeFlagsPrinter:
-    """A class that prints a decoded form of an instance_flags value.
-
-    This class uses a global named TYPE_FLAGS, which is a list of
-    all defined TypeFlag values.  Using a global allows us to compute
-    this list only once.
-
-    This class relies on a couple of enumeration types being defined.
-    If not, then printing of the instance_flag is going to be degraded,
-    but it's not a fatal error.
-    """
-    def __init__(self, val):
-        self.val = val
-    def __str__(self):
-        global TYPE_FLAGS
-        if TYPE_FLAGS is None:
-            self.init_TYPE_FLAGS()
-        if not self.val:
-            return "0"
-        if TYPE_FLAGS:
-            flag_list = [flag.short_name for flag in TYPE_FLAGS
-                         if self.val & flag.value]
-        else:
-            flag_list = ["???"]
-        return "0x%x [%s]" % (self.val, "|".join(flag_list))
-    def init_TYPE_FLAGS(self):
-        """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
-        This operation requires the search of a couple of enumeration types.
-        If not found, a warning is printed on stdout, and TYPE_FLAGS is
-        set to the empty list.
-
-        The resulting list is sorted by increasing value, to facilitate
-        printing of the list of flags used in an instance_flags value.
-        """
-        global TYPE_FLAGS
-        TYPE_FLAGS = []
-        try:
-            iflags = gdb.lookup_type("enum type_instance_flag_value")
-        except:
-            print("Warning: Cannot find enum type_instance_flag_value type.")
-            print("         `struct type' pretty-printer will be degraded")
-            return
-        TYPE_FLAGS = [TypeFlag(field.name, field.enumval)
-                      for field in iflags.fields()]
-        TYPE_FLAGS.sort()
-
-class StructTypePrettyPrinter:
-    """Pretty-print an object of type struct type"""
-    def __init__(self, val):
-        self.val = val
-    def to_string(self):
-        fields = []
-        fields.append("pointer_type = %s" % self.val['pointer_type'])
-        fields.append("reference_type = %s" % self.val['reference_type'])
-        fields.append("chain = %s" % self.val['reference_type'])
-        fields.append("instance_flags = %s"
-                      % TypeFlagsPrinter(self.val['instance_flags']))
-        fields.append("length = %d" % self.val['length'])
-        fields.append("main_type = %s" % self.val['main_type'])
-        return "\n{" + ",\n ".join(fields) + "}"
-
-class StructMainTypePrettyPrinter:
-    """Pretty-print an objet of type main_type"""
-    def __init__(self, val):
-        self.val = val
-    def flags_to_string(self):
-        """struct main_type contains a series of components that
-        are one-bit ints whose name start with "flag_".  For instance:
-        flag_unsigned, flag_stub, etc.  In essence, these components are
-        really boolean flags, and this method prints a short synthetic
-        version of the value of all these flags.  For instance, if
-        flag_unsigned and flag_static are the only components set to 1,
-        this function will return "unsigned|static".
-        """
-        fields = [field.name.replace("flag_", "")
-                  for field in self.val.type.fields()
-                  if field.name.startswith("flag_")
-                     and self.val[field.name]]
-        return "|".join(fields)
-    def owner_to_string(self):
-        """Return an image of component "owner".
-        """
-        if self.val['flag_objfile_owned'] != 0:
-            return "%s (objfile)" % self.val['owner']['objfile']
-        else:
-            return "%s (gdbarch)" % self.val['owner']['gdbarch']
-    def struct_field_location_img(self, field_val):
-        """Return an image of the loc component inside the given field
-        gdb.Value.
-        """
-        loc_val = field_val['loc']
-        loc_kind = str(field_val['loc_kind'])
-        if loc_kind == "FIELD_LOC_KIND_BITPOS":
-            return 'bitpos = %d' % loc_val['bitpos']
-        elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
-            return 'enumval = %d' % loc_val['enumval']
-        elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
-            return 'physaddr = 0x%x' % loc_val['physaddr']
-        elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
-            return 'physname = %s' % loc_val['physname']
-        elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
-            return 'dwarf_block = %s' % loc_val['dwarf_block']
-        else:
-            return 'loc = ??? (unsupported loc_kind value)'
-    def struct_field_img(self, fieldno):
-        """Return an image of the main_type field number FIELDNO.
-        """
-        f = self.val['flds_bnds']['fields'][fieldno]
-        label = "flds_bnds.fields[%d]:" % fieldno
-        if f['artificial']:
-            label += " (artificial)"
-        fields = []
-        fields.append("name = %s" % f['name'])
-        fields.append("type = %s" % f['type'])
-        fields.append("loc_kind = %s" % f['loc_kind'])
-        fields.append("bitsize = %d" % f['bitsize'])
-        fields.append(self.struct_field_location_img(f))
-        return label + "\n" + "  {" + ",\n   ".join(fields) + "}"
-    def bounds_img(self):
-        """Return an image of the main_type bounds.
-        """
-        b = self.val['flds_bnds']['bounds'].dereference()
-        low = str(b['low'])
-        if b['low_undefined'] != 0:
-            low += " (undefined)"
-        high = str(b['high'])
-        if b['high_undefined'] != 0:
-            high += " (undefined)"
-        return "flds_bnds.bounds = {%s, %s}" % (low, high)
-    def type_specific_img(self):
-        """Return a string image of the main_type type_specific union.
-        Only the relevant component of that union is printed (based on
-        the value of the type_specific_kind field.
-        """
-        type_specific_kind = str(self.val['type_specific_field'])
-        type_specific = self.val['type_specific']
-        if type_specific_kind == "TYPE_SPECIFIC_NONE":
-            img = 'type_specific_field = %s' % type_specific_kind
-        elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
-            img = "cplus_stuff = %s" % type_specific['cplus_stuff']
-        elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
-            img = ("gnat_stuff = {descriptive_type = %s}"
-                   % type_specific['gnat_stuff']['descriptive_type'])
-        elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
-            img = "floatformat[0..1] = %s" % type_specific['floatformat']
-        elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
-            img = ("calling_convention = %d"
-                   % type_specific['func_stuff']['calling_convention'])
-            # tail_call_list is not printed.
-        elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
-            img = "self_type = %s" % type_specific['self_type']
-        else:
-            img = ("type_specific = ??? (unknown type_secific_kind: %s)"
-                   % type_specific_kind)
-        return img
-
-    def to_string(self):
-        """Return a pretty-printed image of our main_type.
-        """
-        fields = []
-        fields.append("name = %s" % self.val['name'])
-        fields.append("tag_name = %s" % self.val['tag_name'])
-        fields.append("code = %s" % self.val['code'])
-        fields.append("flags = [%s]" % self.flags_to_string())
-        fields.append("owner = %s" % self.owner_to_string())
-        fields.append("target_type = %s" % self.val['target_type'])
-        if self.val['nfields'] > 0:
-            for fieldno in range(self.val['nfields']):
-                fields.append(self.struct_field_img(fieldno))
-        if self.val['code'] == gdb.TYPE_CODE_RANGE:
-            fields.append(self.bounds_img())
-        fields.append(self.type_specific_img())
-
-        return "\n{" + ",\n ".join(fields) + "}"
-
-def type_lookup_function(val):
-    """A routine that returns the correct pretty printer for VAL
-    if appropriate.  Returns None otherwise.
-    """
-    if val.type.tag == "type":
-        return StructTypePrettyPrinter(val)
-    elif val.type.tag == "main_type":
-        return StructMainTypePrettyPrinter(val)
-    return None
-
-def register_pretty_printer(objfile):
-    """A routine to register a pretty-printer against the given OBJFILE.
-    """
-    objfile.pretty_printers.append(type_lookup_function)
-
-if __name__ == "__main__":
-    if gdb.current_objfile() is not None:
-        # This is the case where this script is being "auto-loaded"
-        # for a given objfile.  Register the pretty-printer for that
-        # objfile.
-        register_pretty_printer(gdb.current_objfile())
-    else:
-        # We need to locate the objfile corresponding to the GDB
-        # executable, and register the pretty-printer for that objfile.
-        # FIXME: The condition used to match the objfile is too simplistic
-        # and will not work on Windows.
-        for objfile in gdb.objfiles():
-            if os.path.basename(objfile.filename) == "gdb":
-                objfile.pretty_printers.append(type_lookup_function)
diff --git a/gdb/gdb-gdb.py.in b/gdb/gdb-gdb.py.in
new file mode 100644 (file)
index 0000000..b8bb1ad
--- /dev/null
@@ -0,0 +1,252 @@
+# Copyright (C) 2009-2018 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import gdb
+import os.path
+
+class TypeFlag:
+    """A class that allows us to store a flag name, its short name,
+    and its value.
+
+    In the GDB sources, struct type has a component called instance_flags
+    in which the value is the addition of various flags.  These flags are
+    defined by the enumerates type_instance_flag_value.  This class helps us
+    recreate a list with all these flags that is easy to manipulate and sort.
+    Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
+    attribute is provided that strips this prefix.
+
+    ATTRIBUTES
+      name:  The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
+      value: The associated value.
+      short_name: The enumeration name, with the suffix stripped.
+    """
+    def __init__(self, name, value):
+        self.name = name
+        self.value = value
+        self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '')
+    def __cmp__(self, other):
+        """Sort by value order."""
+        return self.value.__cmp__(other.value)
+
+# A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
+# stored as TypeFlags objects.  Lazy-initialized.
+TYPE_FLAGS = None
+
+class TypeFlagsPrinter:
+    """A class that prints a decoded form of an instance_flags value.
+
+    This class uses a global named TYPE_FLAGS, which is a list of
+    all defined TypeFlag values.  Using a global allows us to compute
+    this list only once.
+
+    This class relies on a couple of enumeration types being defined.
+    If not, then printing of the instance_flag is going to be degraded,
+    but it's not a fatal error.
+    """
+    def __init__(self, val):
+        self.val = val
+    def __str__(self):
+        global TYPE_FLAGS
+        if TYPE_FLAGS is None:
+            self.init_TYPE_FLAGS()
+        if not self.val:
+            return "0"
+        if TYPE_FLAGS:
+            flag_list = [flag.short_name for flag in TYPE_FLAGS
+                         if self.val & flag.value]
+        else:
+            flag_list = ["???"]
+        return "0x%x [%s]" % (self.val, "|".join(flag_list))
+    def init_TYPE_FLAGS(self):
+        """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
+        This operation requires the search of a couple of enumeration types.
+        If not found, a warning is printed on stdout, and TYPE_FLAGS is
+        set to the empty list.
+
+        The resulting list is sorted by increasing value, to facilitate
+        printing of the list of flags used in an instance_flags value.
+        """
+        global TYPE_FLAGS
+        TYPE_FLAGS = []
+        try:
+            iflags = gdb.lookup_type("enum type_instance_flag_value")
+        except:
+            print("Warning: Cannot find enum type_instance_flag_value type.")
+            print("         `struct type' pretty-printer will be degraded")
+            return
+        TYPE_FLAGS = [TypeFlag(field.name, field.enumval)
+                      for field in iflags.fields()]
+        TYPE_FLAGS.sort()
+
+class StructTypePrettyPrinter:
+    """Pretty-print an object of type struct type"""
+    def __init__(self, val):
+        self.val = val
+    def to_string(self):
+        fields = []
+        fields.append("pointer_type = %s" % self.val['pointer_type'])
+        fields.append("reference_type = %s" % self.val['reference_type'])
+        fields.append("chain = %s" % self.val['reference_type'])
+        fields.append("instance_flags = %s"
+                      % TypeFlagsPrinter(self.val['instance_flags']))
+        fields.append("length = %d" % self.val['length'])
+        fields.append("main_type = %s" % self.val['main_type'])
+        return "\n{" + ",\n ".join(fields) + "}"
+
+class StructMainTypePrettyPrinter:
+    """Pretty-print an objet of type main_type"""
+    def __init__(self, val):
+        self.val = val
+    def flags_to_string(self):
+        """struct main_type contains a series of components that
+        are one-bit ints whose name start with "flag_".  For instance:
+        flag_unsigned, flag_stub, etc.  In essence, these components are
+        really boolean flags, and this method prints a short synthetic
+        version of the value of all these flags.  For instance, if
+        flag_unsigned and flag_static are the only components set to 1,
+        this function will return "unsigned|static".
+        """
+        fields = [field.name.replace("flag_", "")
+                  for field in self.val.type.fields()
+                  if field.name.startswith("flag_")
+                     and self.val[field.name]]
+        return "|".join(fields)
+    def owner_to_string(self):
+        """Return an image of component "owner".
+        """
+        if self.val['flag_objfile_owned'] != 0:
+            return "%s (objfile)" % self.val['owner']['objfile']
+        else:
+            return "%s (gdbarch)" % self.val['owner']['gdbarch']
+    def struct_field_location_img(self, field_val):
+        """Return an image of the loc component inside the given field
+        gdb.Value.
+        """
+        loc_val = field_val['loc']
+        loc_kind = str(field_val['loc_kind'])
+        if loc_kind == "FIELD_LOC_KIND_BITPOS":
+            return 'bitpos = %d' % loc_val['bitpos']
+        elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
+            return 'enumval = %d' % loc_val['enumval']
+        elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
+            return 'physaddr = 0x%x' % loc_val['physaddr']
+        elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
+            return 'physname = %s' % loc_val['physname']
+        elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
+            return 'dwarf_block = %s' % loc_val['dwarf_block']
+        else:
+            return 'loc = ??? (unsupported loc_kind value)'
+    def struct_field_img(self, fieldno):
+        """Return an image of the main_type field number FIELDNO.
+        """
+        f = self.val['flds_bnds']['fields'][fieldno]
+        label = "flds_bnds.fields[%d]:" % fieldno
+        if f['artificial']:
+            label += " (artificial)"
+        fields = []
+        fields.append("name = %s" % f['name'])
+        fields.append("type = %s" % f['type'])
+        fields.append("loc_kind = %s" % f['loc_kind'])
+        fields.append("bitsize = %d" % f['bitsize'])
+        fields.append(self.struct_field_location_img(f))
+        return label + "\n" + "  {" + ",\n   ".join(fields) + "}"
+    def bounds_img(self):
+        """Return an image of the main_type bounds.
+        """
+        b = self.val['flds_bnds']['bounds'].dereference()
+        low = str(b['low'])
+        if b['low_undefined'] != 0:
+            low += " (undefined)"
+        high = str(b['high'])
+        if b['high_undefined'] != 0:
+            high += " (undefined)"
+        return "flds_bnds.bounds = {%s, %s}" % (low, high)
+    def type_specific_img(self):
+        """Return a string image of the main_type type_specific union.
+        Only the relevant component of that union is printed (based on
+        the value of the type_specific_kind field.
+        """
+        type_specific_kind = str(self.val['type_specific_field'])
+        type_specific = self.val['type_specific']
+        if type_specific_kind == "TYPE_SPECIFIC_NONE":
+            img = 'type_specific_field = %s' % type_specific_kind
+        elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
+            img = "cplus_stuff = %s" % type_specific['cplus_stuff']
+        elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
+            img = ("gnat_stuff = {descriptive_type = %s}"
+                   % type_specific['gnat_stuff']['descriptive_type'])
+        elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
+            img = "floatformat[0..1] = %s" % type_specific['floatformat']
+        elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
+            img = ("calling_convention = %d"
+                   % type_specific['func_stuff']['calling_convention'])
+            # tail_call_list is not printed.
+        elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
+            img = "self_type = %s" % type_specific['self_type']
+        else:
+            img = ("type_specific = ??? (unknown type_secific_kind: %s)"
+                   % type_specific_kind)
+        return img
+
+    def to_string(self):
+        """Return a pretty-printed image of our main_type.
+        """
+        fields = []
+        fields.append("name = %s" % self.val['name'])
+        fields.append("tag_name = %s" % self.val['tag_name'])
+        fields.append("code = %s" % self.val['code'])
+        fields.append("flags = [%s]" % self.flags_to_string())
+        fields.append("owner = %s" % self.owner_to_string())
+        fields.append("target_type = %s" % self.val['target_type'])
+        if self.val['nfields'] > 0:
+            for fieldno in range(self.val['nfields']):
+                fields.append(self.struct_field_img(fieldno))
+        if self.val['code'] == gdb.TYPE_CODE_RANGE:
+            fields.append(self.bounds_img())
+        fields.append(self.type_specific_img())
+
+        return "\n{" + ",\n ".join(fields) + "}"
+
+def type_lookup_function(val):
+    """A routine that returns the correct pretty printer for VAL
+    if appropriate.  Returns None otherwise.
+    """
+    if val.type.tag == "type":
+        return StructTypePrettyPrinter(val)
+    elif val.type.tag == "main_type":
+        return StructMainTypePrettyPrinter(val)
+    return None
+
+def register_pretty_printer(objfile):
+    """A routine to register a pretty-printer against the given OBJFILE.
+    """
+    objfile.pretty_printers.append(type_lookup_function)
+
+if __name__ == "__main__":
+    if gdb.current_objfile() is not None:
+        # This is the case where this script is being "auto-loaded"
+        # for a given objfile.  Register the pretty-printer for that
+        # objfile.
+        register_pretty_printer(gdb.current_objfile())
+    else:
+        # We need to locate the objfile corresponding to the GDB
+        # executable, and register the pretty-printer for that objfile.
+        # FIXME: The condition used to match the objfile is too simplistic
+        # and will not work on Windows.
+        for objfile in gdb.objfiles():
+            if os.path.basename(objfile.filename) == "gdb":
+                objfile.pretty_printers.append(type_lookup_function)