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