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