GDB (xrefs)
FrameDecorator.py
Go to the documentation of this file.
1 # Copyright (C) 2013-2015 Free Software Foundation, Inc.
2 
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 
16 import gdb
17 
18 # This small code snippet deals with problem of strings in Python 2.x
19 # and Python 3.x. Python 2.x has str and unicode classes which are
20 # sub-classes of basestring. In Python 3.x all strings are encoded
21 # and basestring has been removed.
22 try:
23  basestring
24 except NameError:
25  basestring = str
26 
27 class FrameDecorator(object):
28  """Basic implementation of a Frame Decorator"""
29 
30  """ This base frame decorator decorates a frame or another frame
31  decorator, and provides convenience methods. If this object is
32  wrapping a frame decorator, defer to that wrapped object's method
33  if it has one. This allows for frame decorators that have
34  sub-classed FrameDecorator object, but also wrap other frame
35  decorators on the same frame to correctly execute.
36 
37  E.g
38 
39  If the result of frame filters running means we have one gdb.Frame
40  wrapped by multiple frame decorators, all sub-classed from
41  FrameDecorator, the resulting hierarchy will be:
42 
43  Decorator1
44  -- (wraps) Decorator2
45  -- (wraps) FrameDecorator
46  -- (wraps) gdb.Frame
47 
48  In this case we have two frame decorators, both of which are
49  sub-classed from FrameDecorator. If Decorator1 just overrides the
50  'function' method, then all of the other methods are carried out
51  by the super-class FrameDecorator. But Decorator2 may have
52  overriden other methods, so FrameDecorator will look at the
53  'base' parameter and defer to that class's methods. And so on,
54  down the chain."""
55 
56  # 'base' can refer to a gdb.Frame or another frame decorator. In
57  # the latter case, the child class will have called the super
58  # method and _base will be an object conforming to the Frame Filter
59  # class.
60  def __init__(self, base):
61  self._base = base
62 
63  @staticmethod
64  def _is_limited_frame(frame):
65  """Internal utility to determine if the frame is special or
66  limited."""
67  sal = frame.find_sal()
68 
69  if (not sal.symtab or not sal.symtab.filename
70  or frame.type() == gdb.DUMMY_FRAME
71  or frame.type() == gdb.SIGTRAMP_FRAME):
72 
73  return True
74 
75  return False
76 
77  def elided(self):
78  """Return any elided frames that this class might be
79  wrapping, or None."""
80  if hasattr(self._base, "elided"):
81  return self._base.elided()
82 
83  return None
84 
85  def function(self):
86  """ Return the name of the frame's function or an address of
87  the function of the frame. First determine if this is a
88  special frame. If not, try to determine filename from GDB's
89  frame internal function API. Finally, if a name cannot be
90  determined return the address. If this function returns an
91  address, GDB will attempt to determine the function name from
92  its internal minimal symbols store (for example, for inferiors
93  without debug-info)."""
94 
95  # Both gdb.Frame, and FrameDecorator have a method called
96  # "function", so determine which object this is.
97  if not isinstance(self._base, gdb.Frame):
98  if hasattr(self._base, "function"):
99  # If it is not a gdb.Frame, and there is already a
100  # "function" method, use that.
101  return self._base.function()
102 
103  frame = self.inferior_frame()
104 
105  if frame.type() == gdb.DUMMY_FRAME:
106  return "<function called from gdb>"
107  elif frame.type() == gdb.SIGTRAMP_FRAME:
108  return "<signal handler called>"
109 
110  func = frame.function()
111 
112  # If we cannot determine the function name, return the
113  # address. If GDB detects an integer value from this function
114  # it will attempt to find the function name from minimal
115  # symbols via its own internal functions.
116  if func == None:
117  pc = frame.pc()
118  return pc
119 
120  return str(func)
121 
122  def address(self):
123  """ Return the address of the frame's pc"""
124 
125  if hasattr(self._base, "address"):
126  return self._base.address()
127 
128  frame = self.inferior_frame()
129  return frame.pc()
130 
131  def filename(self):
132  """ Return the filename associated with this frame, detecting
133  and returning the appropriate library name is this is a shared
134  library."""
135 
136  if hasattr(self._base, "filename"):
137  return self._base.filename()
138 
139  frame = self.inferior_frame()
140  sal = frame.find_sal()
141  if not sal.symtab or not sal.symtab.filename:
142  pc = frame.pc()
143  return gdb.solib_name(pc)
144  else:
145  return sal.symtab.filename
146 
147  def frame_args(self):
148  """ Return an iterable of frame arguments for this frame, if
149  any. The iterable object contains objects conforming with the
150  Symbol/Value interface. If there are no frame arguments, or
151  if this frame is deemed to be a special case, return None."""
152 
153  if hasattr(self._base, "frame_args"):
154  return self._base.frame_args()
155 
156  frame = self.inferior_frame()
157  if self._is_limited_frame(frame):
158  return None
159 
160  args = FrameVars(frame)
161  return args.fetch_frame_args()
162 
163  def frame_locals(self):
164  """ Return an iterable of local variables for this frame, if
165  any. The iterable object contains objects conforming with the
166  Symbol/Value interface. If there are no frame locals, or if
167  this frame is deemed to be a special case, return None."""
168 
169  if hasattr(self._base, "frame_locals"):
170  return self._base.frame_locals()
171 
172  frame = self.inferior_frame()
173  if self._is_limited_frame(frame):
174  return None
175 
176  args = FrameVars(frame)
177  return args.fetch_frame_locals()
178 
179  def line(self):
180  """ Return line number information associated with the frame's
181  pc. If symbol table/line information does not exist, or if
182  this frame is deemed to be a special case, return None"""
183 
184  if hasattr(self._base, "line"):
185  return self._base.line()
186 
187  frame = self.inferior_frame()
188  if self._is_limited_frame(frame):
189  return None
190 
191  sal = frame.find_sal()
192  if (sal):
193  return sal.line
194  else:
195  return None
196 
197  def inferior_frame(self):
198  """ Return the gdb.Frame underpinning this frame decorator."""
199 
200  # If 'base' is a frame decorator, we want to call its inferior
201  # frame method. If '_base' is a gdb.Frame, just return that.
202  if hasattr(self._base, "inferior_frame"):
203  return self._base.inferior_frame()
204  return self._base
205 
206 class SymValueWrapper(object):
207  """A container class conforming to the Symbol/Value interface
208  which holds frame locals or frame arguments."""
209  def __init__(self, symbol, value):
210  self.sym = symbol
211  self.val = value
212 
213  def value(self):
214  """ Return the value associated with this symbol, or None"""
215  return self.val
216 
217  def symbol(self):
218  """ Return the symbol, or Python text, associated with this
219  symbol, or None"""
220  return self.sym
221 
222 class FrameVars(object):
223 
224  """Utility class to fetch and store frame local variables, or
225  frame arguments."""
226 
227  def __init__(self, frame):
228  self.frame = frame
229  self.symbol_class = {
230  gdb.SYMBOL_LOC_STATIC: True,
231  gdb.SYMBOL_LOC_REGISTER: True,
232  gdb.SYMBOL_LOC_ARG: True,
233  gdb.SYMBOL_LOC_REF_ARG: True,
234  gdb.SYMBOL_LOC_LOCAL: True,
235  gdb.SYMBOL_LOC_REGPARM_ADDR: True,
236  gdb.SYMBOL_LOC_COMPUTED: True
237  }
238 
239  def fetch_b(self, sym):
240  """ Local utility method to determine if according to Symbol
241  type whether it should be included in the iterator. Not all
242  symbols are fetched, and only symbols that return
243  True from this method should be fetched."""
244 
245  # SYM may be a string instead of a symbol in the case of
246  # synthetic local arguments or locals. If that is the case,
247  # always fetch.
248  if isinstance(sym, basestring):
249  return True
250 
251  sym_type = sym.addr_class
252 
253  return self.symbol_class.get(sym_type, False)
254 
256  """Public utility method to fetch frame local variables for
257  the stored frame. Frame arguments are not fetched. If there
258  are no frame local variables, return an empty list."""
259  lvars = []
260 
261  try:
262  block = self.frame.block()
263  except RuntimeError:
264  block = None
265 
266  while block != None:
267  if block.is_global or block.is_static:
268  break
269  for sym in block:
270  if sym.is_argument:
271  continue;
272  if self.fetch_b(sym):
273  lvars.append(SymValueWrapper(sym, None))
274 
275  block = block.superblock
276 
277  return lvars
278 
279  def fetch_frame_args(self):
280  """Public utility method to fetch frame arguments for the
281  stored frame. Frame arguments are the only type fetched. If
282  there are no frame argument variables, return an empty list."""
283 
284  args = []
285 
286  try:
287  block = self.frame.block()
288  except RuntimeError:
289  block = None
290 
291  while block != None:
292  if block.function != None:
293  break
294  block = block.superblock
295 
296  if block != None:
297  for sym in block:
298  if not sym.is_argument:
299  continue;
300  args.append(SymValueWrapper(sym, None))
301 
302  return args
def __init__(self, symbol, value)