From patchwork Fri Jun 15 21:27:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 27876 Received: (qmail 62218 invoked by alias); 15 Jun 2018 21:27:52 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 62203 invoked by uid 89); 15 Jun 2018 21:27:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.2 spammy=objet X-HELO: sesbmg22.ericsson.net Received: from sesbmg22.ericsson.net (HELO sesbmg22.ericsson.net) (193.180.251.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 15 Jun 2018 21:27:46 +0000 Received: from ESESSHC011.ericsson.se (Unknown_Domain [153.88.183.51]) by sesbmg22.ericsson.net (Symantec Mail Security) with SMTP id D0.8E.02679.F4F242B5; Fri, 15 Jun 2018 23:27:43 +0200 (CEST) Received: from ESESSMR506.ericsson.se (153.88.183.128) by ESESSHC011.ericsson.se (153.88.183.51) with Microsoft SMTP Server (TLS) id 14.3.382.0; Fri, 15 Jun 2018 23:27:34 +0200 Received: from ESESBMB504.ericsson.se (153.88.183.171) by ESESSMR506.ericsson.se (153.88.183.128) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3; Fri, 15 Jun 2018 23:27:33 +0200 Received: from NAM05-DM3-obe.outbound.protection.outlook.com (153.88.183.157) by ESESBMB504.ericsson.se (153.88.183.171) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3 via Frontend Transport; Fri, 15 Jun 2018 23:27:33 +0200 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=simon.marchi@ericsson.com; Received: from elxacz23q12.ca.am.ericsson.se (192.75.88.130) by DM6PR15MB2394.namprd15.prod.outlook.com (2603:10b6:5:8d::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.863.16; Fri, 15 Jun 2018 21:27:30 +0000 From: Simon Marchi To: CC: Simon Marchi Subject: [PATCH 1/3] Copy gdb-gdb.py to build dir Date: Fri, 15 Jun 2018 17:27:19 -0400 Message-ID: <1529098041-2212-1-git-send-email-simon.marchi@ericsson.com> MIME-Version: 1.0 X-ClientProxiedBy: SN6PR08CA0019.namprd08.prod.outlook.com (2603:10b6:805:66::32) To DM6PR15MB2394.namprd15.prod.outlook.com (2603:10b6:5:8d::28) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 40816aaf-3381-4a06-28c8-08d5d306cd38 X-MS-TrafficTypeDiagnostic: DM6PR15MB2394: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(788757137089)(17755550239193); X-MS-Exchange-SenderADCheck: 1 X-Forefront-PRVS: 0704670F76 Received-SPF: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jun 2018 21:27:30.5715 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 40816aaf-3381-4a06-28c8-08d5d306cd38 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR15MB2394 X-OriginatorOrg: ericsson.com X-IsSubscribed: yes 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/Makefile.in | 11 ++- gdb/configure | 9 +- gdb/configure.ac | 2 +- gdb/gdb-gdb.py | 252 ------------------------------------------------------ gdb/gdb-gdb.py.in | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 270 insertions(+), 256 deletions(-) delete mode 100644 gdb/gdb-gdb.py create mode 100644 gdb/gdb-gdb.py.in diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 354a636..5934cd6 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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 \ diff --git a/gdb/configure b/gdb/configure index 4186f7e..6d4ae6a 100755 --- a/gdb/configure +++ b/gdb/configure @@ -17693,7 +17693,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 @@ -18409,6 +18409,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" ;; @@ -19040,6 +19041,12 @@ 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) case x$CONFIG_HEADERS in xconfig.h:config.in) diff --git a/gdb/configure.ac b/gdb/configure.ac index e1f630c..1cf7de2 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -2306,7 +2306,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 index b8bb1ad..0000000 --- a/gdb/gdb-gdb.py +++ /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 . - -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 index 0000000..b8bb1ad --- /dev/null +++ b/gdb/gdb-gdb.py.in @@ -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 . + +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)