GDB (API)
|
00001 # Type utilities. 00002 # Copyright (C) 2010-2013 Free Software Foundation, Inc. 00003 00004 # This program is free software; you can redistribute it and/or modify 00005 # it under the terms of the GNU General Public License as published by 00006 # the Free Software Foundation; either version 3 of the License, or 00007 # (at your option) any later version. 00008 # 00009 # This program is distributed in the hope that it will be useful, 00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 # GNU General Public License for more details. 00013 # 00014 # You should have received a copy of the GNU General Public License 00015 # along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 00017 """Utilities for working with gdb.Types.""" 00018 00019 import gdb 00020 00021 00022 def get_basic_type(type_): 00023 """Return the "basic" type of a type. 00024 00025 Arguments: 00026 type_: The type to reduce to its basic type. 00027 00028 Returns: 00029 type_ with const/volatile is stripped away, 00030 and typedefs/references converted to the underlying type. 00031 """ 00032 00033 while (type_.code == gdb.TYPE_CODE_REF or 00034 type_.code == gdb.TYPE_CODE_TYPEDEF): 00035 if type_.code == gdb.TYPE_CODE_REF: 00036 type_ = type_.target() 00037 else: 00038 type_ = type_.strip_typedefs() 00039 return type_.unqualified() 00040 00041 00042 def has_field(type_, field): 00043 """Return True if a type has the specified field. 00044 00045 Arguments: 00046 type_: The type to examine. 00047 It must be one of gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION. 00048 field: The name of the field to look up. 00049 00050 Returns: 00051 True if the field is present either in type_ or any baseclass. 00052 00053 Raises: 00054 TypeError: The type is not a struct or union. 00055 """ 00056 00057 type_ = get_basic_type(type_) 00058 if (type_.code != gdb.TYPE_CODE_STRUCT and 00059 type_.code != gdb.TYPE_CODE_UNION): 00060 raise TypeError("not a struct or union") 00061 for f in type_.fields(): 00062 if f.is_base_class: 00063 if has_field(f.type, field): 00064 return True 00065 else: 00066 # NOTE: f.name could be None 00067 if f.name == field: 00068 return True 00069 return False 00070 00071 00072 def make_enum_dict(enum_type): 00073 """Return a dictionary from a program's enum type. 00074 00075 Arguments: 00076 enum_type: The enum to compute the dictionary for. 00077 00078 Returns: 00079 The dictionary of the enum. 00080 00081 Raises: 00082 TypeError: The type is not an enum. 00083 """ 00084 00085 if enum_type.code != gdb.TYPE_CODE_ENUM: 00086 raise TypeError("not an enum type") 00087 enum_dict = {} 00088 for field in enum_type.fields(): 00089 # The enum's value is stored in "enumval". 00090 enum_dict[field.name] = field.enumval 00091 return enum_dict 00092 00093 00094 def deep_items (type_): 00095 """Return an iterator that recursively traverses anonymous fields. 00096 00097 Arguments: 00098 type_: The type to traverse. It should be one of 00099 gdb.TYPE_CODE_STRUCT or gdb.TYPE_CODE_UNION. 00100 00101 Returns: 00102 an iterator similar to gdb.Type.iteritems(), i.e., it returns 00103 pairs of key, value, but for any anonymous struct or union 00104 field that field is traversed recursively, depth-first. 00105 """ 00106 for k, v in type_.iteritems (): 00107 if k: 00108 yield k, v 00109 else: 00110 for i in deep_items (v.type): 00111 yield i 00112 00113 class TypePrinter(object): 00114 """The base class for type printers. 00115 00116 Instances of this type can be used to substitute type names during 00117 'ptype'. 00118 00119 A type printer must have at least 'name' and 'enabled' attributes, 00120 and supply an 'instantiate' method. 00121 00122 The 'instantiate' method must either return None, or return an 00123 object which has a 'recognize' method. This method must accept a 00124 gdb.Type argument and either return None, meaning that the type 00125 was not recognized, or a string naming the type. 00126 """ 00127 00128 def __init__(self, name): 00129 self.name = name 00130 self.enabled = True 00131 00132 def instantiate(self): 00133 return None 00134 00135 # Helper function for computing the list of type recognizers. 00136 def _get_some_type_recognizers(result, plist): 00137 for printer in plist: 00138 if printer.enabled: 00139 inst = printer.instantiate() 00140 if inst is not None: 00141 result.append(inst) 00142 return None 00143 00144 def get_type_recognizers(): 00145 "Return a list of the enabled type recognizers for the current context." 00146 result = [] 00147 00148 # First try the objfiles. 00149 for objfile in gdb.objfiles(): 00150 _get_some_type_recognizers(result, objfile.type_printers) 00151 # Now try the program space. 00152 _get_some_type_recognizers(result, gdb.current_progspace().type_printers) 00153 # Finally, globals. 00154 _get_some_type_recognizers(result, gdb.type_printers) 00155 00156 return result 00157 00158 def apply_type_recognizers(recognizers, type_obj): 00159 """Apply the given list of type recognizers to the type TYPE_OBJ. 00160 If any recognizer in the list recognizes TYPE_OBJ, returns the name 00161 given by the recognizer. Otherwise, this returns None.""" 00162 for r in recognizers: 00163 result = r.recognize(type_obj) 00164 if result is not None: 00165 return result 00166 return None 00167 00168 def register_type_printer(locus, printer): 00169 """Register a type printer. 00170 PRINTER is the type printer instance. 00171 LOCUS is either an objfile, a program space, or None, indicating 00172 global registration.""" 00173 00174 if locus is None: 00175 locus = gdb 00176 locus.type_printers.insert(0, printer)