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