GDB (API)
|
00001 # Pretty-printer 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 pretty-printers.""" 00018 00019 import gdb 00020 import gdb.types 00021 import re 00022 import sys 00023 00024 if sys.version_info[0] > 2: 00025 # Python 3 removed basestring and long 00026 basestring = str 00027 long = int 00028 00029 class PrettyPrinter(object): 00030 """A basic pretty-printer. 00031 00032 Attributes: 00033 name: A unique string among all printers for the context in which 00034 it is defined (objfile, progspace, or global(gdb)), and should 00035 meaningfully describe what can be pretty-printed. 00036 E.g., "StringPiece" or "protobufs". 00037 subprinters: An iterable object with each element having a `name' 00038 attribute, and, potentially, "enabled" attribute. 00039 Or this is None if there are no subprinters. 00040 enabled: A boolean indicating if the printer is enabled. 00041 00042 Subprinters are for situations where "one" pretty-printer is actually a 00043 collection of several printers. E.g., The libstdc++ pretty-printer has 00044 a pretty-printer for each of several different types, based on regexps. 00045 """ 00046 00047 # While one might want to push subprinters into the subclass, it's 00048 # present here to formalize such support to simplify 00049 # commands/pretty_printers.py. 00050 00051 def __init__(self, name, subprinters=None): 00052 self.name = name 00053 self.subprinters = subprinters 00054 self.enabled = True 00055 00056 def __call__(self, val): 00057 # The subclass must define this. 00058 raise NotImplementedError("PrettyPrinter __call__") 00059 00060 00061 class SubPrettyPrinter(object): 00062 """Baseclass for sub-pretty-printers. 00063 00064 Sub-pretty-printers needn't use this, but it formalizes what's needed. 00065 00066 Attributes: 00067 name: The name of the subprinter. 00068 enabled: A boolean indicating if the subprinter is enabled. 00069 """ 00070 00071 def __init__(self, name): 00072 self.name = name 00073 self.enabled = True 00074 00075 00076 def register_pretty_printer(obj, printer, replace=False): 00077 """Register pretty-printer PRINTER with OBJ. 00078 00079 The printer is added to the front of the search list, thus one can override 00080 an existing printer if one needs to. Use a different name when overriding 00081 an existing printer, otherwise an exception will be raised; multiple 00082 printers with the same name are disallowed. 00083 00084 Arguments: 00085 obj: Either an objfile, progspace, or None (in which case the printer 00086 is registered globally). 00087 printer: Either a function of one argument (old way) or any object 00088 which has attributes: name, enabled, __call__. 00089 replace: If True replace any existing copy of the printer. 00090 Otherwise if the printer already exists raise an exception. 00091 00092 Returns: 00093 Nothing. 00094 00095 Raises: 00096 TypeError: A problem with the type of the printer. 00097 ValueError: The printer's name contains a semicolon ";". 00098 RuntimeError: A printer with the same name is already registered. 00099 00100 If the caller wants the printer to be listable and disableable, it must 00101 follow the PrettyPrinter API. This applies to the old way (functions) too. 00102 If printer is an object, __call__ is a method of two arguments: 00103 self, and the value to be pretty-printed. See PrettyPrinter. 00104 """ 00105 00106 # Watch for both __name__ and name. 00107 # Functions get the former for free, but we don't want to use an 00108 # attribute named __foo__ for pretty-printers-as-objects. 00109 # If printer has both, we use `name'. 00110 if not hasattr(printer, "__name__") and not hasattr(printer, "name"): 00111 raise TypeError("printer missing attribute: name") 00112 if hasattr(printer, "name") and not hasattr(printer, "enabled"): 00113 raise TypeError("printer missing attribute: enabled") 00114 if not hasattr(printer, "__call__"): 00115 raise TypeError("printer missing attribute: __call__") 00116 00117 if obj is None: 00118 if gdb.parameter("verbose"): 00119 gdb.write("Registering global %s pretty-printer ...\n" % name) 00120 obj = gdb 00121 else: 00122 if gdb.parameter("verbose"): 00123 gdb.write("Registering %s pretty-printer for %s ...\n" % 00124 (printer.name, obj.filename)) 00125 00126 if hasattr(printer, "name"): 00127 if not isinstance(printer.name, basestring): 00128 raise TypeError("printer name is not a string") 00129 # If printer provides a name, make sure it doesn't contain ";". 00130 # Semicolon is used by the info/enable/disable pretty-printer commands 00131 # to delimit subprinters. 00132 if printer.name.find(";") >= 0: 00133 raise ValueError("semicolon ';' in printer name") 00134 # Also make sure the name is unique. 00135 # Alas, we can't do the same for functions and __name__, they could 00136 # all have a canonical name like "lookup_function". 00137 # PERF: gdb records printers in a list, making this inefficient. 00138 i = 0 00139 for p in obj.pretty_printers: 00140 if hasattr(p, "name") and p.name == printer.name: 00141 if replace: 00142 del obj.pretty_printers[i] 00143 break 00144 else: 00145 raise RuntimeError("pretty-printer already registered: %s" % 00146 printer.name) 00147 i = i + 1 00148 00149 obj.pretty_printers.insert(0, printer) 00150 00151 00152 class RegexpCollectionPrettyPrinter(PrettyPrinter): 00153 """Class for implementing a collection of regular-expression based pretty-printers. 00154 00155 Intended usage: 00156 00157 pretty_printer = RegexpCollectionPrettyPrinter("my_library") 00158 pretty_printer.add_printer("myclass1", "^myclass1$", MyClass1Printer) 00159 ... 00160 pretty_printer.add_printer("myclassN", "^myclassN$", MyClassNPrinter) 00161 register_pretty_printer(obj, pretty_printer) 00162 """ 00163 00164 class RegexpSubprinter(SubPrettyPrinter): 00165 def __init__(self, name, regexp, gen_printer): 00166 super(RegexpCollectionPrettyPrinter.RegexpSubprinter, self).__init__(name) 00167 self.regexp = regexp 00168 self.gen_printer = gen_printer 00169 self.compiled_re = re.compile(regexp) 00170 00171 def __init__(self, name): 00172 super(RegexpCollectionPrettyPrinter, self).__init__(name, []) 00173 00174 def add_printer(self, name, regexp, gen_printer): 00175 """Add a printer to the list. 00176 00177 The printer is added to the end of the list. 00178 00179 Arguments: 00180 name: The name of the subprinter. 00181 regexp: The regular expression, as a string. 00182 gen_printer: A function/method that given a value returns an 00183 object to pretty-print it. 00184 00185 Returns: 00186 Nothing. 00187 """ 00188 00189 # NOTE: A previous version made the name of each printer the regexp. 00190 # That makes it awkward to pass to the enable/disable commands (it's 00191 # cumbersome to make a regexp of a regexp). So now the name is a 00192 # separate parameter. 00193 00194 self.subprinters.append(self.RegexpSubprinter(name, regexp, 00195 gen_printer)) 00196 00197 def __call__(self, val): 00198 """Lookup the pretty-printer for the provided value.""" 00199 00200 # Get the type name. 00201 typename = gdb.types.get_basic_type(val.type).tag 00202 if not typename: 00203 return None 00204 00205 # Iterate over table of type regexps to determine 00206 # if a printer is registered for that type. 00207 # Return an instantiation of the printer if found. 00208 for printer in self.subprinters: 00209 if printer.enabled and printer.compiled_re.search(typename): 00210 return printer.gen_printer(val) 00211 00212 # Cannot find a pretty printer. Return None. 00213 return None 00214 00215 # A helper class for printing enum types. This class is instantiated 00216 # with a list of enumerators to print a particular Value. 00217 class _EnumInstance: 00218 def __init__(self, enumerators, val): 00219 self.enumerators = enumerators 00220 self.val = val 00221 00222 def to_string(self): 00223 flag_list = [] 00224 v = long(self.val) 00225 any_found = False 00226 for (e_name, e_value) in self.enumerators: 00227 if v & e_value != 0: 00228 flag_list.append(e_name) 00229 v = v & ~e_value 00230 any_found = True 00231 if not any_found or v != 0: 00232 # Leftover value. 00233 flag_list.append('<unknown: 0x%x>' % v) 00234 return "0x%x [%s]" % (self.val, " | ".join(flag_list)) 00235 00236 class FlagEnumerationPrinter(PrettyPrinter): 00237 """A pretty-printer which can be used to print a flag-style enumeration. 00238 A flag-style enumeration is one where the enumerators are or'd 00239 together to create values. The new printer will print these 00240 symbolically using '|' notation. The printer must be registered 00241 manually. This printer is most useful when an enum is flag-like, 00242 but has some overlap. GDB's built-in printing will not handle 00243 this case, but this printer will attempt to.""" 00244 00245 def __init__(self, enum_type): 00246 super(FlagEnumerationPrinter, self).__init__(enum_type) 00247 self.initialized = False 00248 00249 def __call__(self, val): 00250 if not self.initialized: 00251 self.initialized = True 00252 flags = gdb.lookup_type(self.name) 00253 self.enumerators = [] 00254 for field in flags.fields(): 00255 self.enumerators.append((field.name, field.enumval)) 00256 # Sorting the enumerators by value usually does the right 00257 # thing. 00258 self.enumerators.sort(key = lambda x: x.enumval) 00259 00260 if self.enabled: 00261 return _EnumInstance(self.enumerators, val) 00262 else: 00263 return None