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