]> Git Repo - binutils.git/blob - gdb/python/lib/gdb/FrameDecorator.py
69a0a9a4d7fa2d51e9048f38aa8abd11ebc3797f
[binutils.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.033513 seconds and 2 git commands to generate.