d6bfa1ec3d372cbb9ddff8d22373677511963faf
[external/binutils.git] / gdb / python / lib / gdb / FrameDecorator.py
1 # Copyright (C) 2013-2016 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 class FrameDecorator(object):
28     """Basic implementation of a Frame Decorator"""
29
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.
36
37     E.g
38
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:
42
43     Decorator1
44       -- (wraps) Decorator2
45         -- (wraps) FrameDecorator
46           -- (wraps) gdb.Frame
47
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,
54     down the chain."""
55
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
59     # class.
60     def __init__(self, base):
61         self._base = base
62
63     @staticmethod
64     def _is_limited_frame(frame):
65         """Internal utility to determine if the frame is special or
66         limited."""
67         sal = frame.find_sal()
68
69         if (not sal.symtab or not sal.symtab.filename
70             or frame.type() == gdb.DUMMY_FRAME
71             or frame.type() == gdb.SIGTRAMP_FRAME):
72
73             return True
74
75         return False
76
77     def elided(self):
78         """Return any elided frames that this class might be
79         wrapping, or None."""
80         if hasattr(self._base, "elided"):
81             return self._base.elided()
82
83         return None
84
85     def function(self):
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)."""
94
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()
102
103         frame = self.inferior_frame()
104
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>"
109
110         func = frame.function()
111
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.
116         if func == None:
117             pc = frame.pc()
118             return pc
119
120         return str(func)
121
122     def address(self):
123         """ Return the address of the frame's pc"""
124
125         if hasattr(self._base, "address"):
126             return self._base.address()
127
128         frame = self.inferior_frame()
129         return frame.pc()
130
131     def filename(self):
132         """ Return the filename associated with this frame, detecting
133         and returning the appropriate library name is this is a shared
134         library."""
135
136         if hasattr(self._base, "filename"):
137             return self._base.filename()
138
139         frame = self.inferior_frame()
140         sal = frame.find_sal()
141         if not sal.symtab or not sal.symtab.filename:
142             pc = frame.pc()
143             return gdb.solib_name(pc)
144         else:
145             return sal.symtab.filename
146
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."""
152
153         if hasattr(self._base, "frame_args"):
154             return self._base.frame_args()
155
156         frame = self.inferior_frame()
157         if self._is_limited_frame(frame):
158             return None
159
160         args = FrameVars(frame)
161         return args.fetch_frame_args()
162
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."""
168
169         if hasattr(self._base, "frame_locals"):
170             return self._base.frame_locals()
171
172         frame = self.inferior_frame()
173         if self._is_limited_frame(frame):
174             return None
175
176         args = FrameVars(frame)
177         return args.fetch_frame_locals()
178
179     def line(self):
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"""
183
184         if hasattr(self._base, "line"):
185             return self._base.line()
186
187         frame = self.inferior_frame()
188         if self._is_limited_frame(frame):
189             return None
190
191         sal = frame.find_sal()
192         if (sal):
193             return sal.line
194         else:
195             return None
196
197     def inferior_frame(self):
198         """ Return the gdb.Frame underpinning this frame decorator."""
199
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()
204         return self._base
205
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):
210         self.sym = symbol
211         self.val = value
212
213     def value(self):
214         """ Return the value associated with this symbol, or None"""
215         return self.val
216
217     def symbol(self):
218         """ Return the symbol, or Python text, associated with this
219         symbol, or None"""
220         return self.sym
221
222 class FrameVars(object):
223
224     """Utility class to fetch and store frame local variables, or
225     frame arguments."""
226
227     def __init__(self, frame):
228         self.frame = 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
237             }
238
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."""
244
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,
247         # always fetch.
248         if isinstance(sym, basestring):
249             return True
250
251         sym_type = sym.addr_class
252
253         return self.symbol_class.get(sym_type, False)
254
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."""
259         lvars = []
260
261         try:
262             block = self.frame.block()
263         except RuntimeError:
264             block = None
265
266         while block != None:
267             if block.is_global or block.is_static:
268                 break
269             for sym in block:
270                 if sym.is_argument:
271                     continue;
272                 if self.fetch_b(sym):
273                     lvars.append(SymValueWrapper(sym, None))
274
275             block = block.superblock
276
277         return lvars
278
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."""
283
284         args = []
285
286         try:
287             block = self.frame.block()
288         except RuntimeError:
289             block = None
290
291         while block != None:
292             if block.function != None:
293                 break
294             block = block.superblock
295
296         if block != None:
297             for sym in block:
298                 if not sym.is_argument:
299                     continue;
300                 args.append(SymValueWrapper(sym, None))
301
302         return args