GDB (API)
/home/stan/gdb/src/gdb/python/lib/gdb/FrameDecorator.py
Go to the documentation of this file.
00001 # Copyright (C) 2013 Free Software Foundation, Inc.
00002 
00003 # This program is free software; you can redistribute it and/or modify
00004 # it under the terms of the GNU General Public License as published by
00005 # the Free Software Foundation; either version 3 of the License, or
00006 # (at your option) any later version.
00007 #
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 #
00013 # You should have received a copy of the GNU General Public License
00014 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 import gdb
00017 
00018 # This small code snippet deals with problem of strings in Python 2.x
00019 # and Python 3.x.  Python 2.x has str and unicode classes which are
00020 # sub-classes of basestring.  In Python 3.x all strings are encoded
00021 # and basestring has been removed.
00022 try:
00023     basestring
00024 except NameError:
00025     basestring = str
00026 
00027 class FrameDecorator(object):
00028     """Basic implementation of a Frame Decorator"""
00029 
00030     """ This base frame decorator decorates a frame or another frame
00031     decorator, and provides convenience methods.  If this object is
00032     wrapping a frame decorator, defer to that wrapped object's method
00033     if it has one.  This allows for frame decorators that have
00034     sub-classed FrameDecorator object, but also wrap other frame
00035     decorators on the same frame to correctly execute.
00036 
00037     E.g
00038 
00039     If the result of frame filters running means we have one gdb.Frame
00040     wrapped by multiple frame decorators, all sub-classed from
00041     FrameDecorator, the resulting hierarchy will be:
00042 
00043     Decorator1
00044       -- (wraps) Decorator2
00045         -- (wraps) FrameDecorator
00046           -- (wraps) gdb.Frame
00047 
00048     In this case we have two frame decorators, both of which are
00049     sub-classed from FrameDecorator.  If Decorator1 just overrides the
00050     'function' method, then all of the other methods are carried out
00051     by the super-class FrameDecorator.  But Decorator2 may have
00052     overriden other methods, so FrameDecorator will look at the
00053     'base' parameter and defer to that class's methods.  And so on,
00054     down the chain."""
00055 
00056     # 'base' can refer to a gdb.Frame or another frame decorator.  In
00057     # the latter case, the child class will have called the super
00058     # method and _base will be an object conforming to the Frame Filter
00059     # class.
00060     def __init__(self, base):
00061         self._base = base
00062 
00063     @staticmethod
00064     def _is_limited_frame(frame):
00065         """Internal utility to determine if the frame is special or
00066         limited."""
00067         sal = frame.find_sal()
00068 
00069         if (not sal.symtab or not sal.symtab.filename
00070             or frame.type() == gdb.DUMMY_FRAME
00071             or frame.type() == gdb.SIGTRAMP_FRAME):
00072 
00073             return True
00074 
00075         return False
00076 
00077     def elided(self):
00078         """Return any elided frames that this class might be
00079         wrapping, or None."""
00080         if hasattr(self._base, "elided"):
00081             return self._base.elided()
00082 
00083         return None
00084 
00085     def function(self):
00086         """ Return the name of the frame's function or an address of
00087         the function of the frame.  First determine if this is a
00088         special frame.  If not, try to determine filename from GDB's
00089         frame internal function API.  Finally, if a name cannot be
00090         determined return the address.  If this function returns an
00091         address, GDB will attempt to determine the function name from
00092         its internal minimal symbols store (for example, for inferiors
00093         without debug-info)."""
00094 
00095         # Both gdb.Frame, and FrameDecorator have a method called
00096         # "function", so determine which object this is.
00097         if not isinstance(self._base, gdb.Frame):
00098             if hasattr(self._base, "function"):
00099                 # If it is not a gdb.Frame, and there is already a
00100                 # "function" method, use that.
00101                 return self._base.function()
00102 
00103         frame = self.inferior_frame()
00104 
00105         if frame.type() == gdb.DUMMY_FRAME:
00106             return "<function called from gdb>"
00107         elif frame.type() == gdb.SIGTRAMP_FRAME:
00108             return "<signal handler called>"
00109 
00110         func = frame.function()
00111 
00112         # If we cannot determine the function name, return the
00113         # address.  If GDB detects an integer value from this function
00114         # it will attempt to find the function name from minimal
00115         # symbols via its own internal functions.
00116         if func == None:
00117             pc = frame.pc()
00118             return pc
00119 
00120         return str(func)
00121 
00122     def address(self):
00123         """ Return the address of the frame's pc"""
00124 
00125         if hasattr(self._base, "address"):
00126             return self._base.address()
00127 
00128         frame = self.inferior_frame()
00129         return frame.pc()
00130 
00131     def filename(self):
00132         """ Return the filename associated with this frame, detecting
00133         and returning the appropriate library name is this is a shared
00134         library."""
00135 
00136         if hasattr(self._base, "filename"):
00137             return self._base.filename()
00138 
00139         frame = self.inferior_frame()
00140         sal = frame.find_sal()
00141         if not sal.symtab or not sal.symtab.filename:
00142             pc = frame.pc()
00143             return gdb.solib_name(pc)
00144         else:
00145             return sal.symtab.filename
00146 
00147     def frame_args(self):
00148         """ Return an iterable of frame arguments for this frame, if
00149         any.  The iterable object contains objects conforming with the
00150         Symbol/Value interface.  If there are no frame arguments, or
00151         if this frame is deemed to be a special case, return None."""
00152 
00153         if hasattr(self._base, "frame_args"):
00154             return self._base.frame_args()
00155 
00156         frame = self.inferior_frame()
00157         if self._is_limited_frame(frame):
00158             return None
00159 
00160         args = FrameVars(frame)
00161         return args.fetch_frame_args()
00162 
00163     def frame_locals(self):
00164         """ Return an iterable of local variables for this frame, if
00165         any.  The iterable object contains objects conforming with the
00166         Symbol/Value interface.  If there are no frame locals, or if
00167         this frame is deemed to be a special case, return None."""
00168 
00169         if hasattr(self._base, "frame_locals"):
00170             return self._base.frame_locals()
00171 
00172         frame = self.inferior_frame()
00173         if self._is_limited_frame(frame):
00174             return None
00175 
00176         args = FrameVars(frame)
00177         return args.fetch_frame_locals()
00178 
00179     def line(self):
00180         """ Return line number information associated with the frame's
00181         pc.  If symbol table/line information does not exist, or if
00182         this frame is deemed to be a special case, return None"""
00183 
00184         if hasattr(self._base, "line"):
00185             return self._base.line()
00186 
00187         frame = self.inferior_frame()
00188         if self._is_limited_frame(frame):
00189             return None
00190 
00191         sal = frame.find_sal()
00192         if (sal):
00193             return sal.line
00194         else:
00195             return None
00196 
00197     def inferior_frame(self):
00198         """ Return the gdb.Frame underpinning this frame decorator."""
00199 
00200         # If 'base' is a frame decorator, we want to call its inferior
00201         # frame method.  If '_base' is a gdb.Frame, just return that.
00202         if hasattr(self._base, "inferior_frame"):
00203             return self._base.inferior_frame()
00204         return self._base
00205 
00206 class SymValueWrapper(object):
00207     """A container class conforming to the Symbol/Value interface
00208     which holds frame locals or frame arguments."""
00209     def __init__(self, symbol, value):
00210         self.sym = symbol
00211         self.val = value
00212 
00213     def value(self):
00214         """ Return the value associated with this symbol, or None"""
00215         return self.val
00216 
00217     def symbol(self):
00218         """ Return the symbol, or Python text, associated with this
00219         symbol, or None"""
00220         return self.sym
00221 
00222 class FrameVars(object):
00223 
00224     """Utility class to fetch and store frame local variables, or
00225     frame arguments."""
00226 
00227     def __init__(self, frame):
00228         self.frame = frame
00229         self.symbol_class = {
00230             gdb.SYMBOL_LOC_STATIC: True,
00231             gdb.SYMBOL_LOC_REGISTER: True,
00232             gdb.SYMBOL_LOC_ARG: True,
00233             gdb.SYMBOL_LOC_REF_ARG: True,
00234             gdb.SYMBOL_LOC_LOCAL: True,
00235             gdb.SYMBOL_LOC_REGPARM_ADDR: True,
00236             gdb.SYMBOL_LOC_COMPUTED: True
00237             }
00238 
00239     def fetch_b(self, sym):
00240         """ Local utility method to determine if according to Symbol
00241         type whether it should be included in the iterator.  Not all
00242         symbols are fetched, and only symbols that return
00243         True from this method should be fetched."""
00244 
00245         # SYM may be a string instead of a symbol in the case of
00246         # synthetic local arguments or locals.  If that is the case,
00247         # always fetch.
00248         if isinstance(sym, basestring):
00249             return True
00250 
00251         sym_type = sym.addr_class
00252 
00253         return self.symbol_class.get(sym_type, False)
00254 
00255     def fetch_frame_locals(self):
00256         """Public utility method to fetch frame local variables for
00257         the stored frame.  Frame arguments are not fetched.  If there
00258         are no frame local variables, return an empty list."""
00259         lvars = []
00260 
00261         block = self.frame.block()
00262 
00263         while block != None:
00264             if block.is_global or block.is_static:
00265                 break
00266             for sym in block:
00267                 if sym.is_argument:
00268                     continue;
00269                 if self.fetch_b(sym):
00270                     lvars.append(SymValueWrapper(sym, None))
00271 
00272             block = block.superblock
00273 
00274         return lvars
00275 
00276     def fetch_frame_args(self):
00277         """Public utility method to fetch frame arguments for the
00278         stored frame.  Frame arguments are the only type fetched.  If
00279         there are no frame argument variables, return an empty list."""
00280 
00281         args = []
00282         block = self.frame.block()
00283         while block != None:
00284             if block.function != None:
00285                 break
00286             block = block.superblock
00287 
00288         if block != None:
00289             for sym in block:
00290                 if not sym.is_argument:
00291                     continue;
00292                 args.append(SymValueWrapper(sym, None))
00293 
00294         return args
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines