GDB (API)
|
00001 # Frame-filter commands. 00002 # Copyright (C) 2013 Free Software Foundation, Inc. 00003 00004 # This program is free software; you can redistribute it and/or modify 00005 # it under the terms of the GNU General Public License as published by 00006 # the Free Software Foundation; either version 3 of the License, or 00007 # (at your option) any later version. 00008 # 00009 # This program is distributed in the hope that it will be useful, 00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 # GNU General Public License for more details. 00013 # 00014 # You should have received a copy of the GNU General Public License 00015 # along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 00017 """GDB commands for working with frame-filters.""" 00018 00019 import sys 00020 import gdb 00021 import copy 00022 from gdb.FrameIterator import FrameIterator 00023 from gdb.FrameDecorator import FrameDecorator 00024 import gdb.frames 00025 import itertools 00026 00027 # GDB Commands. 00028 class SetFilterPrefixCmd(gdb.Command): 00029 """Prefix command for 'set' frame-filter related operations.""" 00030 00031 def __init__(self): 00032 super(SetFilterPrefixCmd, self).__init__("set frame-filter", 00033 gdb.COMMAND_OBSCURE, 00034 gdb.COMPLETE_NONE, True) 00035 00036 class ShowFilterPrefixCmd(gdb.Command): 00037 """Prefix command for 'show' frame-filter related operations.""" 00038 def __init__(self): 00039 super(ShowFilterPrefixCmd, self).__init__("show frame-filter", 00040 gdb.COMMAND_OBSCURE, 00041 gdb.COMPLETE_NONE, True) 00042 class InfoFrameFilter(gdb.Command): 00043 """List all registered Python frame-filters. 00044 00045 Usage: info frame-filters 00046 """ 00047 00048 def __init__(self): 00049 super(InfoFrameFilter, self).__init__("info frame-filter", 00050 gdb.COMMAND_DATA) 00051 @staticmethod 00052 def enabled_string(state): 00053 """Return "Yes" if filter is enabled, otherwise "No".""" 00054 if state: 00055 return "Yes" 00056 else: 00057 return "No" 00058 00059 def list_frame_filters(self, frame_filters): 00060 """ Internal worker function to list and print frame filters 00061 in a dictionary. 00062 00063 Arguments: 00064 frame_filters: The name of the dictionary, as 00065 specified by GDB user commands. 00066 """ 00067 00068 sorted_frame_filters = sorted(frame_filters.items(), 00069 key=lambda i: gdb.frames.get_priority(i[1]), 00070 reverse=True) 00071 00072 if len(sorted_frame_filters) == 0: 00073 print(" No frame filters registered.") 00074 else: 00075 print(" Priority Enabled Name") 00076 for frame_filter in sorted_frame_filters: 00077 name = frame_filter[0] 00078 try: 00079 priority = '{:<8}'.format( 00080 str(gdb.frames.get_priority(frame_filter[1]))) 00081 enabled = '{:<7}'.format( 00082 self.enabled_string(gdb.frames.get_enabled(frame_filter[1]))) 00083 except Exception: 00084 e = sys.exc_info()[1] 00085 print(" Error printing filter '"+name+"': "+str(e)) 00086 else: 00087 print(" %s %s %s" % (priority, enabled, name)) 00088 00089 def print_list(self, title, filter_list, blank_line): 00090 print(title) 00091 self.list_frame_filters(filter_list) 00092 if blank_line: 00093 print("") 00094 00095 def invoke(self, arg, from_tty): 00096 self.print_list("global frame-filters:", gdb.frame_filters, True) 00097 00098 cp = gdb.current_progspace() 00099 self.print_list("progspace %s frame-filters:" % cp.filename, 00100 cp.frame_filters, True) 00101 00102 for objfile in gdb.objfiles(): 00103 self.print_list("objfile %s frame-filters:" % objfile.filename, 00104 objfile.frame_filters, False) 00105 00106 # Internal enable/disable functions. 00107 00108 def _enable_parse_arg(cmd_name, arg): 00109 """ Internal worker function to take an argument from 00110 enable/disable and return a tuple of arguments. 00111 00112 Arguments: 00113 cmd_name: Name of the command invoking this function. 00114 args: The argument as a string. 00115 00116 Returns: 00117 A tuple containing the dictionary, and the argument, or just 00118 the dictionary in the case of "all". 00119 """ 00120 00121 argv = gdb.string_to_argv(arg); 00122 argc = len(argv) 00123 if argv[0] == "all" and argc > 1: 00124 raise gdb.GdbError(cmd_name + ": with 'all' " \ 00125 "you may not specify a filter.") 00126 else: 00127 if argv[0] != "all" and argc != 2: 00128 raise gdb.GdbError(cmd_name + " takes exactly two arguments.") 00129 00130 return argv 00131 00132 def _do_enable_frame_filter(command_tuple, flag): 00133 """Worker for enabling/disabling frame_filters. 00134 00135 Arguments: 00136 command_type: A tuple with the first element being the 00137 frame filter dictionary, and the second being 00138 the frame filter name. 00139 flag: True for Enable, False for Disable. 00140 """ 00141 00142 list_op = command_tuple[0] 00143 op_list = gdb.frames.return_list(list_op) 00144 00145 if list_op == "all": 00146 for item in op_list: 00147 gdb.frames.set_enabled(item, flag) 00148 else: 00149 frame_filter = command_tuple[1] 00150 try: 00151 ff = op_list[frame_filter] 00152 except KeyError: 00153 msg = "frame-filter '" + str(name) + "' not found." 00154 raise gdb.GdbError(msg) 00155 00156 gdb.frames.set_enabled(ff, flag) 00157 00158 def _complete_frame_filter_list(text, word, all_flag): 00159 """Worker for frame filter dictionary name completion. 00160 00161 Arguments: 00162 text: The full text of the command line. 00163 word: The most recent word of the command line. 00164 all_flag: Whether to include the word "all" in completion. 00165 00166 Returns: 00167 A list of suggested frame filter dictionary name completions 00168 from text/word analysis. This list can be empty when there 00169 are no suggestions for completion. 00170 """ 00171 if all_flag == True: 00172 filter_locations = ["all", "global", "progspace"] 00173 else: 00174 filter_locations = ["global", "progspace"] 00175 for objfile in gdb.objfiles(): 00176 filter_locations.append(objfile.filename) 00177 00178 # If the user just asked for completions with no completion 00179 # hints, just return all the frame filter dictionaries we know 00180 # about. 00181 if (text == ""): 00182 return filter_locations 00183 00184 # Otherwise filter on what we know. 00185 flist = filter(lambda x,y=text:x.startswith(y), filter_locations) 00186 00187 # If we only have one completion, complete it and return it. 00188 if len(flist) == 1: 00189 flist[0] = flist[0][len(text)-len(word):] 00190 00191 # Otherwise, return an empty list, or a list of frame filter 00192 # dictionaries that the previous filter operation returned. 00193 return flist 00194 00195 def _complete_frame_filter_name(word, printer_dict): 00196 """Worker for frame filter name completion. 00197 00198 Arguments: 00199 00200 word: The most recent word of the command line. 00201 00202 printer_dict: The frame filter dictionary to search for frame 00203 filter name completions. 00204 00205 Returns: A list of suggested frame filter name completions 00206 from word analysis of the frame filter dictionary. This list 00207 can be empty when there are no suggestions for completion. 00208 """ 00209 00210 printer_keys = printer_dict.keys() 00211 if (word == ""): 00212 return printer_keys 00213 00214 flist = filter(lambda x,y=word:x.startswith(y), printer_keys) 00215 return flist 00216 00217 class EnableFrameFilter(gdb.Command): 00218 """GDB command to disable the specified frame-filter. 00219 00220 Usage: enable frame-filter enable DICTIONARY [NAME] 00221 00222 DICTIONARY is the name of the frame filter dictionary on which to 00223 operate. If dictionary is set to "all", perform operations on all 00224 dictionaries. Named dictionaries are: "global" for the global 00225 frame filter dictionary, "progspace" for the program space's frame 00226 filter dictionary. If either all, or the two named dictionaries 00227 are not specified, the dictionary name is assumed to be the name 00228 of the object-file name. 00229 00230 NAME matches the name of the frame-filter to operate on. If 00231 DICTIONARY is "all", NAME is ignored. 00232 """ 00233 def __init__(self): 00234 super(EnableFrameFilter, self).__init__("enable frame-filter", 00235 gdb.COMMAND_DATA) 00236 def complete(self, text, word): 00237 """Completion function for both frame filter dictionary, and 00238 frame filter name.""" 00239 if text.count(" ") == 0: 00240 return _complete_frame_filter_list(text, word, True) 00241 else: 00242 printer_list = gdb.frames.return_list(text.split()[0].rstrip()) 00243 return _complete_frame_filter_name(word, printer_list) 00244 00245 def invoke(self, arg, from_tty): 00246 command_tuple = _enable_parse_arg("enable frame-filter", arg) 00247 _do_enable_frame_filter(command_tuple, True) 00248 00249 00250 class DisableFrameFilter(gdb.Command): 00251 """GDB command to disable the specified frame-filter. 00252 00253 Usage: disable frame-filter disable DICTIONARY [NAME] 00254 00255 DICTIONARY is the name of the frame filter dictionary on which to 00256 operate. If dictionary is set to "all", perform operations on all 00257 dictionaries. Named dictionaries are: "global" for the global 00258 frame filter dictionary, "progspace" for the program space's frame 00259 filter dictionary. If either all, or the two named dictionaries 00260 are not specified, the dictionary name is assumed to be the name 00261 of the object-file name. 00262 00263 NAME matches the name of the frame-filter to operate on. If 00264 DICTIONARY is "all", NAME is ignored. 00265 """ 00266 def __init__(self): 00267 super(DisableFrameFilter, self).__init__("disable frame-filter", 00268 gdb.COMMAND_DATA) 00269 00270 def complete(self, text, word): 00271 """Completion function for both frame filter dictionary, and 00272 frame filter name.""" 00273 if text.count(" ") == 0: 00274 return _complete_frame_filter_list(text, word, True) 00275 else: 00276 printer_list = gdb.frames.return_list(text.split()[0].rstrip()) 00277 return _complete_frame_filter_name(word, printer_list) 00278 00279 def invoke(self, arg, from_tty): 00280 command_tuple = _enable_parse_arg("disable frame-filter", arg) 00281 _do_enable_frame_filter(command_tuple, False) 00282 00283 class SetFrameFilterPriority(gdb.Command): 00284 """GDB command to set the priority of the specified frame-filter. 00285 00286 Usage: set frame-filter priority DICTIONARY NAME PRIORITY 00287 00288 DICTIONARY is the name of the frame filter dictionary on which to 00289 operate. Named dictionaries are: "global" for the global frame 00290 filter dictionary, "progspace" for the program space's framefilter 00291 dictionary. If either of these two are not specified, the 00292 dictionary name is assumed to be the name of the object-file name. 00293 00294 NAME matches the name of the frame filter to operate on. 00295 00296 PRIORITY is the an integer to assign the new priority to the frame 00297 filter. 00298 """ 00299 00300 def __init__(self): 00301 super(SetFrameFilterPriority, self).__init__("set frame-filter " \ 00302 "priority", 00303 gdb.COMMAND_DATA) 00304 00305 def _parse_pri_arg(self, arg): 00306 """Internal worker to parse a priority from a tuple. 00307 00308 Arguments: 00309 arg: Tuple which contains the arguments from the command. 00310 00311 Returns: 00312 A tuple containing the dictionary, name and priority from 00313 the arguments. 00314 00315 Raises: 00316 gdb.GdbError: An error parsing the arguments. 00317 """ 00318 00319 argv = gdb.string_to_argv(arg); 00320 argc = len(argv) 00321 if argc != 3: 00322 print("set frame-filter priority " \ 00323 "takes exactly three arguments.") 00324 return None 00325 00326 return argv 00327 00328 def _set_filter_priority(self, command_tuple): 00329 """Internal worker for setting priority of frame-filters, by 00330 parsing a tuple and calling _set_priority with the parsed 00331 tuple. 00332 00333 Arguments: 00334 command_tuple: Tuple which contains the arguments from the 00335 command. 00336 """ 00337 00338 list_op = command_tuple[0] 00339 frame_filter = command_tuple[1] 00340 00341 # GDB returns arguments as a string, so convert priority to 00342 # a number. 00343 priority = int(command_tuple[2]) 00344 00345 op_list = gdb.frames.return_list(list_op) 00346 00347 try: 00348 ff = op_list[frame_filter] 00349 except KeyError: 00350 msg = "frame-filter '" + str(name) + "' not found." 00351 raise gdb.GdbError(msg) 00352 00353 gdb.frames.set_priority(ff, priority) 00354 00355 def complete(self, text, word): 00356 """Completion function for both frame filter dictionary, and 00357 frame filter name.""" 00358 if text.count(" ") == 0: 00359 return _complete_frame_filter_list(text, word, False) 00360 else: 00361 printer_list = gdb.frames.return_list(text.split()[0].rstrip()) 00362 return _complete_frame_filter_name(word, printer_list) 00363 00364 def invoke(self, arg, from_tty): 00365 command_tuple = self._parse_pri_arg(arg) 00366 if command_tuple != None: 00367 self._set_filter_priority(command_tuple) 00368 00369 class ShowFrameFilterPriority(gdb.Command): 00370 """GDB command to show the priority of the specified frame-filter. 00371 00372 Usage: show frame-filter priority DICTIONARY NAME 00373 00374 DICTIONARY is the name of the frame filter dictionary on which to 00375 operate. Named dictionaries are: "global" for the global frame 00376 filter dictionary, "progspace" for the program space's framefilter 00377 dictionary. If either of these two are not specified, the 00378 dictionary name is assumed to be the name of the object-file name. 00379 00380 NAME matches the name of the frame-filter to operate on. 00381 """ 00382 00383 def __init__(self): 00384 super(ShowFrameFilterPriority, self).__init__("show frame-filter " \ 00385 "priority", 00386 gdb.COMMAND_DATA) 00387 00388 def _parse_pri_arg(self, arg): 00389 """Internal worker to parse a dictionary and name from a 00390 tuple. 00391 00392 Arguments: 00393 arg: Tuple which contains the arguments from the command. 00394 00395 Returns: 00396 A tuple containing the dictionary, and frame filter name. 00397 00398 Raises: 00399 gdb.GdbError: An error parsing the arguments. 00400 """ 00401 00402 argv = gdb.string_to_argv(arg); 00403 argc = len(argv) 00404 if argc != 2: 00405 print("show frame-filter priority " \ 00406 "takes exactly two arguments.") 00407 return None 00408 00409 return argv 00410 00411 def get_filter_priority(self, frame_filters, name): 00412 """Worker for retrieving the priority of frame_filters. 00413 00414 Arguments: 00415 frame_filters: Name of frame filter dictionary. 00416 name: object to select printers. 00417 00418 Returns: 00419 The priority of the frame filter. 00420 00421 Raises: 00422 gdb.GdbError: A frame filter cannot be found. 00423 """ 00424 00425 op_list = gdb.frames.return_list(frame_filters) 00426 00427 try: 00428 ff = op_list[name] 00429 except KeyError: 00430 msg = "frame-filter '" + str(name) + "' not found." 00431 raise gdb.GdbError(msg) 00432 00433 return gdb.frames.get_priority(ff) 00434 00435 def complete(self, text, word): 00436 """Completion function for both frame filter dictionary, and 00437 frame filter name.""" 00438 00439 if text.count(" ") == 0: 00440 return _complete_frame_filter_list(text, word, False) 00441 else: 00442 printer_list = frame._return_list(text.split()[0].rstrip()) 00443 return _complete_frame_filter_name(word, printer_list) 00444 00445 def invoke(self, arg, from_tty): 00446 command_tuple = self._parse_pri_arg(arg) 00447 if command_tuple == None: 00448 return 00449 filter_name = command_tuple[1] 00450 list_name = command_tuple[0] 00451 try: 00452 priority = self.get_filter_priority(list_name, filter_name); 00453 except Exception: 00454 e = sys.exc_info()[1] 00455 print("Error printing filter priority for '"+name+"':"+str(e)) 00456 else: 00457 print("Priority of filter '" + filter_name + "' in list '" \ 00458 + list_name + "' is: " + str(priority)) 00459 00460 # Register commands 00461 SetFilterPrefixCmd() 00462 ShowFilterPrefixCmd() 00463 InfoFrameFilter() 00464 EnableFrameFilter() 00465 DisableFrameFilter() 00466 SetFrameFilterPriority() 00467 ShowFrameFilterPriority()