]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/FrameDecorator.py
1 # Copyright (C) 2013-2021 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/>.
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.
27 class FrameDecorator(object):
28 """Basic implementation of a Frame Decorator"""
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.
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:
45 -- (wraps) FrameDecorator
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,
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
60 def __init__(self
, base
):
64 def _is_limited_frame(frame
):
65 """Internal utility to determine if the frame is special or
67 sal
= frame
.find_sal()
69 if (not sal
.symtab
or not sal
.symtab
.filename
70 or frame
.type() == gdb
.DUMMY_FRAME
71 or frame
.type() == gdb
.SIGTRAMP_FRAME
):
78 """Return any elided frames that this class might be
80 if hasattr(self
._base
, "elided"):
81 return self
._base
.elided()
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)."""
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()
103 frame
= self
.inferior_frame()
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>"
110 func
= frame
.function()
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.
123 """ Return the address of the frame's pc"""
125 if hasattr(self
._base
, "address"):
126 return self
._base
.address()
128 frame
= self
.inferior_frame()
132 """ Return the filename associated with this frame, detecting
133 and returning the appropriate library name is this is a shared
136 if hasattr(self
._base
, "filename"):
137 return self
._base
.filename()
139 frame
= self
.inferior_frame()
140 sal
= frame
.find_sal()
141 if not sal
.symtab
or not sal
.symtab
.filename
:
143 return gdb
.solib_name(pc
)
145 return sal
.symtab
.filename
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."""
153 if hasattr(self
._base
, "frame_args"):
154 return self
._base
.frame_args()
156 frame
= self
.inferior_frame()
157 if self
._is
_limited
_frame
(frame
):
160 args
= FrameVars(frame
)
161 return args
.fetch_frame_args()
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."""
169 if hasattr(self
._base
, "frame_locals"):
170 return self
._base
.frame_locals()
172 frame
= self
.inferior_frame()
173 if self
._is
_limited
_frame
(frame
):
176 args
= FrameVars(frame
)
177 return args
.fetch_frame_locals()
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"""
184 if hasattr(self
._base
, "line"):
185 return self
._base
.line()
187 frame
= self
.inferior_frame()
188 if self
._is
_limited
_frame
(frame
):
191 sal
= frame
.find_sal()
197 def inferior_frame(self
):
198 """ Return the gdb.Frame underpinning this frame decorator."""
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()
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
):
214 """ Return the value associated with this symbol, or None"""
218 """ Return the symbol, or Python text, associated with this
222 class FrameVars(object):
224 """Utility class to fetch and store frame local variables, or
227 def __init__(self
, 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
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."""
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,
248 if isinstance(sym
, basestring
):
251 sym_type
= sym
.addr_class
253 return self
.symbol_class
.get(sym_type
, False)
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."""
262 block
= self
.frame
.block()
267 if block
.is_global
or block
.is_static
:
272 if self
.fetch_b(sym
):
273 lvars
.append(SymValueWrapper(sym
, None))
275 block
= block
.superblock
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."""
287 block
= self
.frame
.block()
292 if block
.function
!= None:
294 block
= block
.superblock
298 if not sym
.is_argument
:
300 args
.append(SymValueWrapper(sym
, None))