1 # Copyright (C) 2013-2023 Free Software Foundation, Inc.
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.
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.
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/>.
19 class _FrameDecoratorBase(object):
20 """Base class of frame decorators."""
22 # 'base' can refer to a gdb.Frame or another frame decorator. In
23 # the latter case, the child class will have called the super
24 # method and _base will be an object conforming to the Frame Filter
26 def __init__(self
, base
):
30 def __is_limited_frame(frame
):
31 """Internal utility to determine if the frame is special or
33 sal
= frame
.find_sal()
37 or not sal
.symtab
.filename
38 or frame
.type() == gdb
.DUMMY_FRAME
39 or frame
.type() == gdb
.SIGTRAMP_FRAME
46 """Return any elided frames that this class might be
48 if hasattr(self
._base
, "elided"):
49 return self
._base
.elided()
54 """Return the name of the frame's function or an address of
55 the function of the frame. First determine if this is a
56 special frame. If not, try to determine filename from GDB's
57 frame internal function API. Finally, if a name cannot be
58 determined return the address. If this function returns an
59 address, GDB will attempt to determine the function name from
60 its internal minimal symbols store (for example, for inferiors
61 without debug-info)."""
63 # Both gdb.Frame, and FrameDecorator have a method called
64 # "function", so determine which object this is.
65 if not isinstance(self
._base
, gdb
.Frame
):
66 if hasattr(self
._base
, "function"):
67 # If it is not a gdb.Frame, and there is already a
68 # "function" method, use that.
69 return self
._base
.function()
71 frame
= self
.inferior_frame()
73 if frame
.type() == gdb
.DUMMY_FRAME
:
74 return "<function called from gdb>"
75 elif frame
.type() == gdb
.SIGTRAMP_FRAME
:
76 return "<signal handler called>"
79 if not isinstance(func
, str):
84 """Return the address of the frame's pc"""
86 if hasattr(self
._base
, "address"):
87 return self
._base
.address()
89 frame
= self
.inferior_frame()
93 """Return an iterable of frame arguments for this frame, if
94 any. The iterable object contains objects conforming with the
95 Symbol/Value interface. If there are no frame arguments, or
96 if this frame is deemed to be a special case, return None."""
98 if hasattr(self
._base
, "frame_args"):
99 return self
._base
.frame_args()
101 frame
= self
.inferior_frame()
102 if self
.__is
_limited
_frame
(frame
):
105 args
= FrameVars(frame
)
106 return args
.fetch_frame_args()
108 def frame_locals(self
):
109 """Return an iterable of local variables for this frame, if
110 any. The iterable object contains objects conforming with the
111 Symbol/Value interface. If there are no frame locals, or if
112 this frame is deemed to be a special case, return None."""
114 if hasattr(self
._base
, "frame_locals"):
115 return self
._base
.frame_locals()
117 frame
= self
.inferior_frame()
118 if self
.__is
_limited
_frame
(frame
):
121 args
= FrameVars(frame
)
122 return args
.fetch_frame_locals()
125 """Return line number information associated with the frame's
126 pc. If symbol table/line information does not exist, or if
127 this frame is deemed to be a special case, return None"""
129 if hasattr(self
._base
, "line"):
130 return self
._base
.line()
132 frame
= self
.inferior_frame()
133 if self
.__is
_limited
_frame
(frame
):
136 sal
= frame
.find_sal()
142 def inferior_frame(self
):
143 """Return the gdb.Frame underpinning this frame decorator."""
145 # If 'base' is a frame decorator, we want to call its inferior
146 # frame method. If '_base' is a gdb.Frame, just return that.
147 if hasattr(self
._base
, "inferior_frame"):
148 return self
._base
.inferior_frame()
152 class FrameDecorator(_FrameDecoratorBase
):
153 """Basic implementation of a Frame Decorator
155 This base frame decorator decorates a frame or another frame
156 decorator, and provides convenience methods. If this object is
157 wrapping a frame decorator, defer to that wrapped object's method
158 if it has one. This allows for frame decorators that have
159 sub-classed FrameDecorator object, but also wrap other frame
160 decorators on the same frame to correctly execute.
164 If the result of frame filters running means we have one gdb.Frame
165 wrapped by multiple frame decorators, all sub-classed from
166 FrameDecorator, the resulting hierarchy will be:
169 -- (wraps) Decorator2
170 -- (wraps) FrameDecorator
173 In this case we have two frame decorators, both of which are
174 sub-classed from FrameDecorator. If Decorator1 just overrides the
175 'function' method, then all of the other methods are carried out
176 by the super-class FrameDecorator. But Decorator2 may have
177 overriden other methods, so FrameDecorator will look at the
178 'base' parameter and defer to that class's methods. And so on,
182 """Return the filename associated with this frame, detecting
183 and returning the appropriate library name is this is a shared
186 if hasattr(self
._base
, "filename"):
187 return self
._base
.filename()
189 frame
= self
.inferior_frame()
190 sal
= frame
.find_sal()
191 if not sal
.symtab
or not sal
.symtab
.filename
:
193 return gdb
.solib_name(pc
)
195 return sal
.symtab
.filename
198 class DAPFrameDecorator(_FrameDecoratorBase
):
199 """Like FrameDecorator, but has slightly different results
200 for the "filename" method."""
203 """Return the filename associated with this frame, detecting
204 and returning the appropriate library name is this is a shared
207 if hasattr(self
._base
, "filename"):
208 return self
._base
.filename()
210 frame
= self
.inferior_frame()
211 sal
= frame
.find_sal()
212 if sal
.symtab
is not None:
213 return sal
.symtab
.fullname()
216 def frame_locals(self
):
217 """Return an iterable of local variables for this frame, if
218 any. The iterable object contains objects conforming with the
219 Symbol/Value interface. If there are no frame locals, or if
220 this frame is deemed to be a special case, return None."""
222 if hasattr(self
._base
, "frame_locals"):
223 return self
._base
.frame_locals()
225 frame
= self
.inferior_frame()
226 args
= FrameVars(frame
)
227 return args
.fetch_frame_locals(True)
230 class SymValueWrapper(object):
231 """A container class conforming to the Symbol/Value interface
232 which holds frame locals or frame arguments."""
234 # The FRAME argument is needed here because gdb.Symbol doesn't
235 # carry the block with it, and so read_var can't find symbols from
236 # outer (static link) frames.
237 def __init__(self
, frame
, symbol
):
242 """Return the value associated with this symbol, or None"""
243 if self
.frame
is None:
245 return self
.frame
.read_var(self
.sym
)
248 """Return the symbol, or Python text, associated with this
253 class FrameVars(object):
255 """Utility class to fetch and store frame local variables, or
258 def __init__(self
, frame
):
261 def fetch_frame_locals(self
, follow_link
=False):
262 """Public utility method to fetch frame local variables for
263 the stored frame. Frame arguments are not fetched. If there
264 are no frame local variables, return an empty list."""
269 block
= frame
.block()
273 traversed_link
= False
274 while block
is not None:
275 if block
.is_global
or block
.is_static
:
278 # Exclude arguments from the innermost function, but
279 # if we found and traversed a static link, just treat
280 # all such variables as "local".
282 if not traversed_link
:
284 elif not sym
.is_variable
:
285 # We use an 'elif' here because is_variable
286 # returns False for arguments as well. Anyway,
287 # don't include non-variables here.
289 lvars
.append(SymValueWrapper(frame
, sym
))
291 if block
.function
is not None:
294 # If the frame has a static link, follow it here.
295 traversed_link
= True
296 frame
= frame
.static_link()
300 block
= frame
.block()
304 block
= block
.superblock
308 def fetch_frame_args(self
):
309 """Public utility method to fetch frame arguments for the
310 stored frame. Frame arguments are the only type fetched. If
311 there are no frame argument variables, return an empty list."""
316 block
= self
.frame
.block()
320 while block
is not None:
321 if block
.is_global
or block
.is_static
:
324 if not sym
.is_argument
:
326 args
.append(SymValueWrapper(None, sym
))
328 # Stop when the function itself is seen, to avoid showing
329 # variables from outer functions in a nested function.
330 # Note that we don't traverse the static link for
331 # arguments, only for locals.
332 if block
.function
is not None:
335 block
= block
.superblock