blob: 1bbc5ab1ce7c2f3caa580aae5d097b172fdabbb4 [file] [log] [blame]
Ben Cheng7334f0a2014-04-30 14:28:17 -07001# Copyright (C) 2013-2014 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
16import 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.
22try:
23 basestring
24except NameError:
25 basestring = str
26
27class 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
206class 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
222class 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
255 def fetch_frame_locals(self):
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