]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/command/frame_filters.py
Update copyright year range in all GDB files.
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / command / frame_filters.py
1 # Frame-filter commands.
2 # Copyright (C) 2013-2019 Free Software Foundation, Inc.
3
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 """GDB commands for working with frame-filters."""
18
19 import sys
20 import gdb
21 import copy
22 from gdb.FrameIterator import FrameIterator
23 from gdb.FrameDecorator import FrameDecorator
24 import gdb.frames
25 import itertools
26
27 # GDB Commands.
28 class SetFilterPrefixCmd(gdb.Command):
29 """Prefix command for 'set' frame-filter related operations."""
30
31 def __init__(self):
32 super(SetFilterPrefixCmd, self).__init__("set frame-filter",
33 gdb.COMMAND_OBSCURE,
34 gdb.COMPLETE_NONE, True)
35
36 class ShowFilterPrefixCmd(gdb.Command):
37 """Prefix command for 'show' frame-filter related operations."""
38 def __init__(self):
39 super(ShowFilterPrefixCmd, self).__init__("show frame-filter",
40 gdb.COMMAND_OBSCURE,
41 gdb.COMPLETE_NONE, True)
42 class InfoFrameFilter(gdb.Command):
43 """List all registered Python frame-filters.
44
45 Usage: info frame-filters"""
46
47 def __init__(self):
48 super(InfoFrameFilter, self).__init__("info frame-filter",
49 gdb.COMMAND_DATA)
50 @staticmethod
51 def enabled_string(state):
52 """Return "Yes" if filter is enabled, otherwise "No"."""
53 if state:
54 return "Yes"
55 else:
56 return "No"
57
58 def print_list(self, title, frame_filters, blank_line):
59 sorted_frame_filters = sorted(frame_filters.items(),
60 key=lambda i: gdb.frames.get_priority(i[1]),
61 reverse=True)
62
63 if len(sorted_frame_filters) == 0:
64 return 0
65
66 print(title)
67 print(" Priority Enabled Name")
68 for frame_filter in sorted_frame_filters:
69 name = frame_filter[0]
70 try:
71 priority = '{:<8}'.format(
72 str(gdb.frames.get_priority(frame_filter[1])))
73 enabled = '{:<7}'.format(
74 self.enabled_string(gdb.frames.get_enabled(frame_filter[1])))
75 print(" %s %s %s" % (priority, enabled, name))
76 except Exception:
77 e = sys.exc_info()[1]
78 print(" Error printing filter '"+name+"': "+str(e))
79 if blank_line:
80 print("")
81 return 1
82
83 def invoke(self, arg, from_tty):
84 any_printed = self.print_list("global frame-filters:", gdb.frame_filters, True)
85
86 cp = gdb.current_progspace()
87 any_printed += self.print_list("progspace %s frame-filters:" % cp.filename,
88 cp.frame_filters, True)
89
90 for objfile in gdb.objfiles():
91 any_printed += self.print_list("objfile %s frame-filters:" % objfile.filename,
92 objfile.frame_filters, False)
93
94 if any_printed == 0:
95 print ("No frame filters.")
96
97 # Internal enable/disable functions.
98
99 def _enable_parse_arg(cmd_name, arg):
100 """ Internal worker function to take an argument from
101 enable/disable and return a tuple of arguments.
102
103 Arguments:
104 cmd_name: Name of the command invoking this function.
105 args: The argument as a string.
106
107 Returns:
108 A tuple containing the dictionary, and the argument, or just
109 the dictionary in the case of "all".
110 """
111
112 argv = gdb.string_to_argv(arg);
113 argc = len(argv)
114 if argc == 0:
115 raise gdb.GdbError(cmd_name + " requires an argument")
116 if argv[0] == "all":
117 if argc > 1:
118 raise gdb.GdbError(cmd_name + ": with 'all' " \
119 "you may not specify a filter.")
120 elif argc != 2:
121 raise gdb.GdbError(cmd_name + " takes exactly two arguments.")
122
123 return argv
124
125 def _do_enable_frame_filter(command_tuple, flag):
126 """Worker for enabling/disabling frame_filters.
127
128 Arguments:
129 command_type: A tuple with the first element being the
130 frame filter dictionary, and the second being
131 the frame filter name.
132 flag: True for Enable, False for Disable.
133 """
134
135 list_op = command_tuple[0]
136 op_list = gdb.frames.return_list(list_op)
137
138 if list_op == "all":
139 for item in op_list:
140 gdb.frames.set_enabled(item, flag)
141 else:
142 frame_filter = command_tuple[1]
143 try:
144 ff = op_list[frame_filter]
145 except KeyError:
146 msg = "frame-filter '" + str(frame_filter) + "' not found."
147 raise gdb.GdbError(msg)
148
149 gdb.frames.set_enabled(ff, flag)
150
151 def _complete_frame_filter_list(text, word, all_flag):
152 """Worker for frame filter dictionary name completion.
153
154 Arguments:
155 text: The full text of the command line.
156 word: The most recent word of the command line.
157 all_flag: Whether to include the word "all" in completion.
158
159 Returns:
160 A list of suggested frame filter dictionary name completions
161 from text/word analysis. This list can be empty when there
162 are no suggestions for completion.
163 """
164 if all_flag == True:
165 filter_locations = ["all", "global", "progspace"]
166 else:
167 filter_locations = ["global", "progspace"]
168 for objfile in gdb.objfiles():
169 filter_locations.append(objfile.filename)
170
171 # If the user just asked for completions with no completion
172 # hints, just return all the frame filter dictionaries we know
173 # about.
174 if (text == ""):
175 return filter_locations
176
177 # Otherwise filter on what we know.
178 flist = filter(lambda x,y=text:x.startswith(y), filter_locations)
179
180 # If we only have one completion, complete it and return it.
181 if len(flist) == 1:
182 flist[0] = flist[0][len(text)-len(word):]
183
184 # Otherwise, return an empty list, or a list of frame filter
185 # dictionaries that the previous filter operation returned.
186 return flist
187
188 def _complete_frame_filter_name(word, printer_dict):
189 """Worker for frame filter name completion.
190
191 Arguments:
192
193 word: The most recent word of the command line.
194
195 printer_dict: The frame filter dictionary to search for frame
196 filter name completions.
197
198 Returns: A list of suggested frame filter name completions
199 from word analysis of the frame filter dictionary. This list
200 can be empty when there are no suggestions for completion.
201 """
202
203 printer_keys = printer_dict.keys()
204 if (word == ""):
205 return printer_keys
206
207 flist = filter(lambda x,y=word:x.startswith(y), printer_keys)
208 return flist
209
210 class EnableFrameFilter(gdb.Command):
211 """GDB command to enable the specified frame-filter.
212
213 Usage: enable frame-filter DICTIONARY [NAME]
214
215 DICTIONARY is the name of the frame filter dictionary on which to
216 operate. If dictionary is set to "all", perform operations on all
217 dictionaries. Named dictionaries are: "global" for the global
218 frame filter dictionary, "progspace" for the program space's frame
219 filter dictionary. If either all, or the two named dictionaries
220 are not specified, the dictionary name is assumed to be the name
221 of an "objfile" -- a shared library or an executable.
222
223 NAME matches the name of the frame-filter to operate on."""
224 def __init__(self):
225 super(EnableFrameFilter, self).__init__("enable frame-filter",
226 gdb.COMMAND_DATA)
227 def complete(self, text, word):
228 """Completion function for both frame filter dictionary, and
229 frame filter name."""
230 if text.count(" ") == 0:
231 return _complete_frame_filter_list(text, word, True)
232 else:
233 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
234 return _complete_frame_filter_name(word, printer_list)
235
236 def invoke(self, arg, from_tty):
237 command_tuple = _enable_parse_arg("enable frame-filter", arg)
238 _do_enable_frame_filter(command_tuple, True)
239
240
241 class DisableFrameFilter(gdb.Command):
242 """GDB command to disable the specified frame-filter.
243
244 Usage: disable frame-filter DICTIONARY [NAME]
245
246 DICTIONARY is the name of the frame filter dictionary on which to
247 operate. If dictionary is set to "all", perform operations on all
248 dictionaries. Named dictionaries are: "global" for the global
249 frame filter dictionary, "progspace" for the program space's frame
250 filter dictionary. If either all, or the two named dictionaries
251 are not specified, the dictionary name is assumed to be the name
252 of an "objfile" -- a shared library or an executable.
253
254 NAME matches the name of the frame-filter to operate on."""
255 def __init__(self):
256 super(DisableFrameFilter, self).__init__("disable frame-filter",
257 gdb.COMMAND_DATA)
258
259 def complete(self, text, word):
260 """Completion function for both frame filter dictionary, and
261 frame filter name."""
262 if text.count(" ") == 0:
263 return _complete_frame_filter_list(text, word, True)
264 else:
265 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
266 return _complete_frame_filter_name(word, printer_list)
267
268 def invoke(self, arg, from_tty):
269 command_tuple = _enable_parse_arg("disable frame-filter", arg)
270 _do_enable_frame_filter(command_tuple, False)
271
272 class SetFrameFilterPriority(gdb.Command):
273 """GDB command to set the priority of the specified frame-filter.
274
275 Usage: set frame-filter priority DICTIONARY NAME PRIORITY
276
277 DICTIONARY is the name of the frame filter dictionary on which to
278 operate. Named dictionaries are: "global" for the global frame
279 filter dictionary, "progspace" for the program space's framefilter
280 dictionary. If either of these two are not specified, the
281 dictionary name is assumed to be the name of an "objfile" -- a
282 shared library or an executable.
283
284 NAME matches the name of the frame filter to operate on.
285
286 PRIORITY is the an integer to assign the new priority to the frame
287 filter."""
288
289 def __init__(self):
290 super(SetFrameFilterPriority, self).__init__("set frame-filter " \
291 "priority",
292 gdb.COMMAND_DATA)
293
294 def _parse_pri_arg(self, arg):
295 """Internal worker to parse a priority from a tuple.
296
297 Arguments:
298 arg: Tuple which contains the arguments from the command.
299
300 Returns:
301 A tuple containing the dictionary, name and priority from
302 the arguments.
303
304 Raises:
305 gdb.GdbError: An error parsing the arguments.
306 """
307
308 argv = gdb.string_to_argv(arg);
309 argc = len(argv)
310 if argc != 3:
311 print("set frame-filter priority " \
312 "takes exactly three arguments.")
313 return None
314
315 return argv
316
317 def _set_filter_priority(self, command_tuple):
318 """Internal worker for setting priority of frame-filters, by
319 parsing a tuple and calling _set_priority with the parsed
320 tuple.
321
322 Arguments:
323 command_tuple: Tuple which contains the arguments from the
324 command.
325 """
326
327 list_op = command_tuple[0]
328 frame_filter = command_tuple[1]
329
330 # GDB returns arguments as a string, so convert priority to
331 # a number.
332 priority = int(command_tuple[2])
333
334 op_list = gdb.frames.return_list(list_op)
335
336 try:
337 ff = op_list[frame_filter]
338 except KeyError:
339 msg = "frame-filter '" + str(frame_filter) + "' not found."
340 raise gdb.GdbError(msg)
341
342 gdb.frames.set_priority(ff, priority)
343
344 def complete(self, text, word):
345 """Completion function for both frame filter dictionary, and
346 frame filter name."""
347 if text.count(" ") == 0:
348 return _complete_frame_filter_list(text, word, False)
349 else:
350 printer_list = gdb.frames.return_list(text.split()[0].rstrip())
351 return _complete_frame_filter_name(word, printer_list)
352
353 def invoke(self, arg, from_tty):
354 command_tuple = self._parse_pri_arg(arg)
355 if command_tuple != None:
356 self._set_filter_priority(command_tuple)
357
358 class ShowFrameFilterPriority(gdb.Command):
359 """GDB command to show the priority of the specified frame-filter.
360
361 Usage: show frame-filter priority DICTIONARY NAME
362
363 DICTIONARY is the name of the frame filter dictionary on which to
364 operate. Named dictionaries are: "global" for the global frame
365 filter dictionary, "progspace" for the program space's framefilter
366 dictionary. If either of these two are not specified, the
367 dictionary name is assumed to be the name of an "objfile" -- a
368 shared library or an executable.
369
370 NAME matches the name of the frame-filter to operate on."""
371
372 def __init__(self):
373 super(ShowFrameFilterPriority, self).__init__("show frame-filter " \
374 "priority",
375 gdb.COMMAND_DATA)
376
377 def _parse_pri_arg(self, arg):
378 """Internal worker to parse a dictionary and name from a
379 tuple.
380
381 Arguments:
382 arg: Tuple which contains the arguments from the command.
383
384 Returns:
385 A tuple containing the dictionary, and frame filter name.
386
387 Raises:
388 gdb.GdbError: An error parsing the arguments.
389 """
390
391 argv = gdb.string_to_argv(arg);
392 argc = len(argv)
393 if argc != 2:
394 print("show frame-filter priority " \
395 "takes exactly two arguments.")
396 return None
397
398 return argv
399
400 def get_filter_priority(self, frame_filters, name):
401 """Worker for retrieving the priority of frame_filters.
402
403 Arguments:
404 frame_filters: Name of frame filter dictionary.
405 name: object to select printers.
406
407 Returns:
408 The priority of the frame filter.
409
410 Raises:
411 gdb.GdbError: A frame filter cannot be found.
412 """
413
414 op_list = gdb.frames.return_list(frame_filters)
415
416 try:
417 ff = op_list[name]
418 except KeyError:
419 msg = "frame-filter '" + str(name) + "' not found."
420 raise gdb.GdbError(msg)
421
422 return gdb.frames.get_priority(ff)
423
424 def complete(self, text, word):
425 """Completion function for both frame filter dictionary, and
426 frame filter name."""
427
428 if text.count(" ") == 0:
429 return _complete_frame_filter_list(text, word, False)
430 else:
431 printer_list = frame._return_list(text.split()[0].rstrip())
432 return _complete_frame_filter_name(word, printer_list)
433
434 def invoke(self, arg, from_tty):
435 command_tuple = self._parse_pri_arg(arg)
436 if command_tuple == None:
437 return
438 filter_name = command_tuple[1]
439 list_name = command_tuple[0]
440 try:
441 priority = self.get_filter_priority(list_name, filter_name);
442 except Exception:
443 e = sys.exc_info()[1]
444 print("Error printing filter priority for '"+name+"':"+str(e))
445 else:
446 print("Priority of filter '" + filter_name + "' in list '" \
447 + list_name + "' is: " + str(priority))
448
449 # Register commands
450 SetFilterPrefixCmd()
451 ShowFilterPrefixCmd()
452 InfoFrameFilter()
453 EnableFrameFilter()
454 DisableFrameFilter()
455 SetFrameFilterPriority()
456 ShowFrameFilterPriority()