1*ef5ccd6cSJohn Marino# Copyright (C) 2009-2013 Free Software Foundation, Inc. 2cf7f2e2dSJohn Marino# 3cf7f2e2dSJohn Marino# This file is part of GDB. 4cf7f2e2dSJohn Marino# 5cf7f2e2dSJohn Marino# This program is free software; you can redistribute it and/or modify 6cf7f2e2dSJohn Marino# it under the terms of the GNU General Public License as published by 7cf7f2e2dSJohn Marino# the Free Software Foundation; either version 3 of the License, or 8cf7f2e2dSJohn Marino# (at your option) any later version. 9cf7f2e2dSJohn Marino# 10cf7f2e2dSJohn Marino# This program is distributed in the hope that it will be useful, 11cf7f2e2dSJohn Marino# but WITHOUT ANY WARRANTY; without even the implied warranty of 12cf7f2e2dSJohn Marino# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13cf7f2e2dSJohn Marino# GNU General Public License for more details. 14cf7f2e2dSJohn Marino# 15cf7f2e2dSJohn Marino# You should have received a copy of the GNU General Public License 16cf7f2e2dSJohn Marino# along with this program. If not, see <http://www.gnu.org/licenses/>. 17cf7f2e2dSJohn Marino 18cf7f2e2dSJohn Marinoimport gdb 19cf7f2e2dSJohn Marinoimport os.path 20cf7f2e2dSJohn Marino 21cf7f2e2dSJohn Marinoclass TypeFlag: 22cf7f2e2dSJohn Marino """A class that allows us to store a flag name, its short name, 23cf7f2e2dSJohn Marino and its value. 24cf7f2e2dSJohn Marino 25cf7f2e2dSJohn Marino In the GDB sources, struct type has a component called instance_flags 26cf7f2e2dSJohn Marino in which the value is the addition of various flags. These flags are 27cf7f2e2dSJohn Marino defined by two enumerates: type_flag_value, and type_instance_flag_value. 28cf7f2e2dSJohn Marino This class helps us recreate a list with all these flags that is 29cf7f2e2dSJohn Marino easy to manipulate and sort. Because all flag names start with either 30cf7f2e2dSJohn Marino TYPE_FLAG_ or TYPE_INSTANCE_FLAG_, a short_name attribute is provided 31cf7f2e2dSJohn Marino that strips this prefix. 32cf7f2e2dSJohn Marino 33cf7f2e2dSJohn Marino ATTRIBUTES 34cf7f2e2dSJohn Marino name: The enumeration name (eg: "TYPE_FLAG_UNSIGNED"). 35cf7f2e2dSJohn Marino value: The associated value. 36cf7f2e2dSJohn Marino short_name: The enumeration name, with the suffix stripped. 37cf7f2e2dSJohn Marino """ 38cf7f2e2dSJohn Marino def __init__(self, name, value): 39cf7f2e2dSJohn Marino self.name = name 40cf7f2e2dSJohn Marino self.value = value 41cf7f2e2dSJohn Marino self.short_name = name.replace("TYPE_FLAG_", '') 42cf7f2e2dSJohn Marino if self.short_name == name: 43cf7f2e2dSJohn Marino self.short_name = name.replace("TYPE_INSTANCE_FLAG_", '') 44cf7f2e2dSJohn Marino def __cmp__(self, other): 45cf7f2e2dSJohn Marino """Sort by value order.""" 46cf7f2e2dSJohn Marino return self.value.__cmp__(other.value) 47cf7f2e2dSJohn Marino 48cf7f2e2dSJohn Marino# A list of all existing TYPE_FLAGS_* and TYPE_INSTANCE_FLAGS_* 49cf7f2e2dSJohn Marino# enumerations, stored as TypeFlags objects. Lazy-initialized. 50cf7f2e2dSJohn MarinoTYPE_FLAGS = None 51cf7f2e2dSJohn Marino 52cf7f2e2dSJohn Marinoclass TypeFlagsPrinter: 53cf7f2e2dSJohn Marino """A class that prints a decoded form of an instance_flags value. 54cf7f2e2dSJohn Marino 55cf7f2e2dSJohn Marino This class uses a global named TYPE_FLAGS, which is a list of 56cf7f2e2dSJohn Marino all defined TypeFlag values. Using a global allows us to compute 57cf7f2e2dSJohn Marino this list only once. 58cf7f2e2dSJohn Marino 59cf7f2e2dSJohn Marino This class relies on a couple of enumeration types being defined. 60cf7f2e2dSJohn Marino If not, then printing of the instance_flag is going to be degraded, 61cf7f2e2dSJohn Marino but it's not a fatal error. 62cf7f2e2dSJohn Marino """ 63cf7f2e2dSJohn Marino def __init__(self, val): 64cf7f2e2dSJohn Marino self.val = val 65cf7f2e2dSJohn Marino def __str__(self): 66cf7f2e2dSJohn Marino global TYPE_FLAGS 67cf7f2e2dSJohn Marino if TYPE_FLAGS is None: 68cf7f2e2dSJohn Marino self.init_TYPE_FLAGS() 69cf7f2e2dSJohn Marino if not self.val: 70cf7f2e2dSJohn Marino return "0" 71cf7f2e2dSJohn Marino if TYPE_FLAGS: 72cf7f2e2dSJohn Marino flag_list = [flag.short_name for flag in TYPE_FLAGS 73cf7f2e2dSJohn Marino if self.val & flag.value] 74cf7f2e2dSJohn Marino else: 75cf7f2e2dSJohn Marino flag_list = ["???"] 76cf7f2e2dSJohn Marino return "0x%x [%s]" % (self.val, "|".join(flag_list)) 77cf7f2e2dSJohn Marino def init_TYPE_FLAGS(self): 78cf7f2e2dSJohn Marino """Initialize the TYPE_FLAGS global as a list of TypeFlag objects. 79cf7f2e2dSJohn Marino This operation requires the search of a couple of enumeration types. 80cf7f2e2dSJohn Marino If not found, a warning is printed on stdout, and TYPE_FLAGS is 81cf7f2e2dSJohn Marino set to the empty list. 82cf7f2e2dSJohn Marino 83cf7f2e2dSJohn Marino The resulting list is sorted by increasing value, to facilitate 84cf7f2e2dSJohn Marino printing of the list of flags used in an instance_flags value. 85cf7f2e2dSJohn Marino """ 86cf7f2e2dSJohn Marino global TYPE_FLAGS 87cf7f2e2dSJohn Marino TYPE_FLAGS = [] 88cf7f2e2dSJohn Marino try: 89cf7f2e2dSJohn Marino flags = gdb.lookup_type("enum type_flag_value") 90cf7f2e2dSJohn Marino except: 91cf7f2e2dSJohn Marino print "Warning: Cannot find enum type_flag_value type." 92cf7f2e2dSJohn Marino print " `struct type' pretty-printer will be degraded" 93cf7f2e2dSJohn Marino return 94cf7f2e2dSJohn Marino try: 95cf7f2e2dSJohn Marino iflags = gdb.lookup_type("enum type_instance_flag_value") 96cf7f2e2dSJohn Marino except: 97cf7f2e2dSJohn Marino print "Warning: Cannot find enum type_instance_flag_value type." 98cf7f2e2dSJohn Marino print " `struct type' pretty-printer will be degraded" 99cf7f2e2dSJohn Marino return 100cf7f2e2dSJohn Marino # Note: TYPE_FLAG_MIN is a duplicate of TYPE_FLAG_UNSIGNED, 101cf7f2e2dSJohn Marino # so exclude it from the list we are building. 102*ef5ccd6cSJohn Marino TYPE_FLAGS = [TypeFlag(field.name, field.enumval) 103cf7f2e2dSJohn Marino for field in flags.fields() 104cf7f2e2dSJohn Marino if field.name != 'TYPE_FLAG_MIN'] 105*ef5ccd6cSJohn Marino TYPE_FLAGS += [TypeFlag(field.name, field.enumval) 106cf7f2e2dSJohn Marino for field in iflags.fields()] 107cf7f2e2dSJohn Marino TYPE_FLAGS.sort() 108cf7f2e2dSJohn Marino 109cf7f2e2dSJohn Marinoclass StructTypePrettyPrinter: 110cf7f2e2dSJohn Marino """Pretty-print an object of type struct type""" 111cf7f2e2dSJohn Marino def __init__(self, val): 112cf7f2e2dSJohn Marino self.val = val 113cf7f2e2dSJohn Marino def to_string(self): 114cf7f2e2dSJohn Marino fields = [] 115cf7f2e2dSJohn Marino fields.append("pointer_type = %s" % self.val['pointer_type']) 116cf7f2e2dSJohn Marino fields.append("reference_type = %s" % self.val['reference_type']) 117cf7f2e2dSJohn Marino fields.append("chain = %s" % self.val['reference_type']) 118cf7f2e2dSJohn Marino fields.append("instance_flags = %s" 119cf7f2e2dSJohn Marino % TypeFlagsPrinter(self.val['instance_flags'])) 120cf7f2e2dSJohn Marino fields.append("length = %d" % self.val['length']) 121cf7f2e2dSJohn Marino fields.append("main_type = %s" % self.val['main_type']) 122cf7f2e2dSJohn Marino return "\n{" + ",\n ".join(fields) + "}" 123cf7f2e2dSJohn Marino 124cf7f2e2dSJohn Marinoclass StructMainTypePrettyPrinter: 125cf7f2e2dSJohn Marino """Pretty-print an objet of type main_type""" 126cf7f2e2dSJohn Marino def __init__(self, val): 127cf7f2e2dSJohn Marino self.val = val 128cf7f2e2dSJohn Marino def flags_to_string(self): 129cf7f2e2dSJohn Marino """struct main_type contains a series of components that 130cf7f2e2dSJohn Marino are one-bit ints whose name start with "flag_". For instance: 131cf7f2e2dSJohn Marino flag_unsigned, flag_stub, etc. In essence, these components are 132cf7f2e2dSJohn Marino really boolean flags, and this method prints a short synthetic 133cf7f2e2dSJohn Marino version of the value of all these flags. For instance, if 134cf7f2e2dSJohn Marino flag_unsigned and flag_static are the only components set to 1, 135cf7f2e2dSJohn Marino this function will return "unsigned|static". 136cf7f2e2dSJohn Marino """ 137cf7f2e2dSJohn Marino fields = [field.name.replace("flag_", "") 138cf7f2e2dSJohn Marino for field in self.val.type.fields() 139cf7f2e2dSJohn Marino if field.name.startswith("flag_") 140cf7f2e2dSJohn Marino and self.val[field.name]] 141cf7f2e2dSJohn Marino return "|".join(fields) 142cf7f2e2dSJohn Marino def owner_to_string(self): 143cf7f2e2dSJohn Marino """Return an image of component "owner". 144cf7f2e2dSJohn Marino """ 145cf7f2e2dSJohn Marino if self.val['flag_objfile_owned'] != 0: 146cf7f2e2dSJohn Marino return "%s (objfile)" % self.val['owner']['objfile'] 147cf7f2e2dSJohn Marino else: 148cf7f2e2dSJohn Marino return "%s (gdbarch)" % self.val['owner']['gdbarch'] 149cf7f2e2dSJohn Marino def struct_field_location_img(self, field_val): 150cf7f2e2dSJohn Marino """Return an image of the loc component inside the given field 151cf7f2e2dSJohn Marino gdb.Value. 152cf7f2e2dSJohn Marino """ 153cf7f2e2dSJohn Marino loc_val = field_val['loc'] 154cf7f2e2dSJohn Marino loc_kind = str(field_val['loc_kind']) 155cf7f2e2dSJohn Marino if loc_kind == "FIELD_LOC_KIND_BITPOS": 156cf7f2e2dSJohn Marino return 'bitpos = %d' % loc_val['bitpos'] 157*ef5ccd6cSJohn Marino elif loc_kind == "FIELD_LOC_KIND_ENUMVAL": 158*ef5ccd6cSJohn Marino return 'enumval = %d' % loc_val['enumval'] 159cf7f2e2dSJohn Marino elif loc_kind == "FIELD_LOC_KIND_PHYSADDR": 160cf7f2e2dSJohn Marino return 'physaddr = 0x%x' % loc_val['physaddr'] 161cf7f2e2dSJohn Marino elif loc_kind == "FIELD_LOC_KIND_PHYSNAME": 162cf7f2e2dSJohn Marino return 'physname = %s' % loc_val['physname'] 163a45ae5f8SJohn Marino elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK": 164a45ae5f8SJohn Marino return 'dwarf_block = %s' % loc_val['dwarf_block'] 165cf7f2e2dSJohn Marino else: 166cf7f2e2dSJohn Marino return 'loc = ??? (unsupported loc_kind value)' 167cf7f2e2dSJohn Marino def struct_field_img(self, fieldno): 168cf7f2e2dSJohn Marino """Return an image of the main_type field number FIELDNO. 169cf7f2e2dSJohn Marino """ 170cf7f2e2dSJohn Marino f = self.val['flds_bnds']['fields'][fieldno] 171*ef5ccd6cSJohn Marino label = "flds_bnds.fields[%d]:" % fieldno 172cf7f2e2dSJohn Marino if f['artificial']: 173cf7f2e2dSJohn Marino label += " (artificial)" 174cf7f2e2dSJohn Marino fields = [] 175cf7f2e2dSJohn Marino fields.append("name = %s" % f['name']) 176cf7f2e2dSJohn Marino fields.append("type = %s" % f['type']) 177cf7f2e2dSJohn Marino fields.append("loc_kind = %s" % f['loc_kind']) 178cf7f2e2dSJohn Marino fields.append("bitsize = %d" % f['bitsize']) 179cf7f2e2dSJohn Marino fields.append(self.struct_field_location_img(f)) 180cf7f2e2dSJohn Marino return label + "\n" + " {" + ",\n ".join(fields) + "}" 181cf7f2e2dSJohn Marino def bounds_img(self): 182cf7f2e2dSJohn Marino """Return an image of the main_type bounds. 183cf7f2e2dSJohn Marino """ 184cf7f2e2dSJohn Marino b = self.val['flds_bnds']['bounds'].dereference() 185cf7f2e2dSJohn Marino low = str(b['low']) 186cf7f2e2dSJohn Marino if b['low_undefined'] != 0: 187cf7f2e2dSJohn Marino low += " (undefined)" 188cf7f2e2dSJohn Marino high = str(b['high']) 189cf7f2e2dSJohn Marino if b['high_undefined'] != 0: 190cf7f2e2dSJohn Marino high += " (undefined)" 191*ef5ccd6cSJohn Marino return "flds_bnds.bounds = {%s, %s}" % (low, high) 192cf7f2e2dSJohn Marino def type_specific_img(self): 193cf7f2e2dSJohn Marino """Return a string image of the main_type type_specific union. 194cf7f2e2dSJohn Marino Only the relevant component of that union is printed (based on 195cf7f2e2dSJohn Marino the value of the type_specific_kind field. 196cf7f2e2dSJohn Marino """ 197cf7f2e2dSJohn Marino type_specific_kind = str(self.val['type_specific_field']) 198cf7f2e2dSJohn Marino type_specific = self.val['type_specific'] 199cf7f2e2dSJohn Marino if type_specific_kind == "TYPE_SPECIFIC_NONE": 200cf7f2e2dSJohn Marino img = 'type_specific_field = %s' % type_specific_kind 201cf7f2e2dSJohn Marino elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF": 202cf7f2e2dSJohn Marino img = "cplus_stuff = %s" % type_specific['cplus_stuff'] 203cf7f2e2dSJohn Marino elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF": 204cf7f2e2dSJohn Marino img = ("gnat_stuff = {descriptive_type = %s}" 205cf7f2e2dSJohn Marino % type_specific['gnat_stuff']['descriptive_type']) 206cf7f2e2dSJohn Marino elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT": 207cf7f2e2dSJohn Marino img = "floatformat[0..1] = %s" % type_specific['floatformat'] 208a45ae5f8SJohn Marino elif type_specific_kind == "TYPE_SPECIFIC_FUNC": 209cf7f2e2dSJohn Marino img = ("calling_convention = %d" 210a45ae5f8SJohn Marino % type_specific['func_stuff']['calling_convention']) 211a45ae5f8SJohn Marino # tail_call_list is not printed. 212cf7f2e2dSJohn Marino else: 213cf7f2e2dSJohn Marino img = ("type_specific = ??? (unknown type_secific_kind: %s)" 214cf7f2e2dSJohn Marino % type_specific_kind) 215cf7f2e2dSJohn Marino return img 216cf7f2e2dSJohn Marino 217cf7f2e2dSJohn Marino def to_string(self): 218cf7f2e2dSJohn Marino """Return a pretty-printed image of our main_type. 219cf7f2e2dSJohn Marino """ 220cf7f2e2dSJohn Marino fields = [] 221cf7f2e2dSJohn Marino fields.append("name = %s" % self.val['name']) 222cf7f2e2dSJohn Marino fields.append("tag_name = %s" % self.val['tag_name']) 223cf7f2e2dSJohn Marino fields.append("code = %s" % self.val['code']) 224cf7f2e2dSJohn Marino fields.append("flags = [%s]" % self.flags_to_string()) 225cf7f2e2dSJohn Marino fields.append("owner = %s" % self.owner_to_string()) 226cf7f2e2dSJohn Marino fields.append("target_type = %s" % self.val['target_type']) 227cf7f2e2dSJohn Marino fields.append("vptr_basetype = %s" % self.val['vptr_basetype']) 228cf7f2e2dSJohn Marino if self.val['nfields'] > 0: 229cf7f2e2dSJohn Marino for fieldno in range(self.val['nfields']): 230cf7f2e2dSJohn Marino fields.append(self.struct_field_img(fieldno)) 231cf7f2e2dSJohn Marino if self.val['code'] == gdb.TYPE_CODE_RANGE: 232cf7f2e2dSJohn Marino fields.append(self.bounds_img()) 233cf7f2e2dSJohn Marino fields.append(self.type_specific_img()) 234cf7f2e2dSJohn Marino 235cf7f2e2dSJohn Marino return "\n{" + ",\n ".join(fields) + "}" 236cf7f2e2dSJohn Marino 237cf7f2e2dSJohn Marinodef type_lookup_function(val): 238cf7f2e2dSJohn Marino """A routine that returns the correct pretty printer for VAL 239cf7f2e2dSJohn Marino if appropriate. Returns None otherwise. 240cf7f2e2dSJohn Marino """ 241cf7f2e2dSJohn Marino if val.type.tag == "type": 242cf7f2e2dSJohn Marino return StructTypePrettyPrinter(val) 243cf7f2e2dSJohn Marino elif val.type.tag == "main_type": 244cf7f2e2dSJohn Marino return StructMainTypePrettyPrinter(val) 245cf7f2e2dSJohn Marino return None 246cf7f2e2dSJohn Marino 247cf7f2e2dSJohn Marinodef register_pretty_printer(objfile): 248cf7f2e2dSJohn Marino """A routine to register a pretty-printer against the given OBJFILE. 249cf7f2e2dSJohn Marino """ 250cf7f2e2dSJohn Marino objfile.pretty_printers.append(type_lookup_function) 251cf7f2e2dSJohn Marino 252cf7f2e2dSJohn Marinoif __name__ == "__main__": 253cf7f2e2dSJohn Marino if gdb.current_objfile() is not None: 254cf7f2e2dSJohn Marino # This is the case where this script is being "auto-loaded" 255cf7f2e2dSJohn Marino # for a given objfile. Register the pretty-printer for that 256cf7f2e2dSJohn Marino # objfile. 257cf7f2e2dSJohn Marino register_pretty_printer(gdb.current_objfile()) 258cf7f2e2dSJohn Marino else: 259cf7f2e2dSJohn Marino # We need to locate the objfile corresponding to the GDB 260cf7f2e2dSJohn Marino # executable, and register the pretty-printer for that objfile. 261cf7f2e2dSJohn Marino # FIXME: The condition used to match the objfile is too simplistic 262cf7f2e2dSJohn Marino # and will not work on Windows. 263cf7f2e2dSJohn Marino for objfile in gdb.objfiles(): 264cf7f2e2dSJohn Marino if os.path.basename(objfile.filename) == "gdb": 265cf7f2e2dSJohn Marino objfile.pretty_printers.append(type_lookup_function) 266