GDB (API)
|
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)