1 # GDB 'explore' command. 2 # Copyright (C) 2012-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 """Implementation of the GDB 'explore' command using the GDB Python API.""" 18 19 import gdb 20 import sys 21 22 if sys.version_info[0] > 2: 23 # Python 3 renamed raw_input to input 24 raw_input = input 25 26 class Explorer(object): 27 """Internal class which invokes other explorers.""" 28 29 # This map is filled by the Explorer.init_env() function 30 type_code_to_explorer_map = { } 31 32 _SCALAR_TYPE_LIST = ( 33 gdb.TYPE_CODE_CHAR, 34 gdb.TYPE_CODE_INT, 35 gdb.TYPE_CODE_BOOL, 36 gdb.TYPE_CODE_FLT, 37 gdb.TYPE_CODE_VOID, 38 gdb.TYPE_CODE_ENUM, 39 ) 40 41 @staticmethod 42 def guard_expr(expr): 43 length = len(expr) 44 guard = False 45 46 if expr[0] == '(' and expr[length-1] == ')': 47 pass 48 else: 49 i = 0 50 while i < length: 51 c = expr[i] 52 if (c == '_' or ('a' <= c and c <= 'z') or 53 ('A' <= c and c <= 'Z') or ('0' <= c and c <= '9')): 54 pass 55 else: 56 guard = True 57 break 58 i += 1 59 60 if guard: 61 return "(" + expr + ")" 62 else: 63 return expr 64 65 @staticmethod 66 def explore_expr(expr, value, is_child): 67 """Main function to explore an expression value. 68 69 Arguments: 70 expr: The expression string that is being explored. 71 value: The gdb.Value value of the expression. 72 is_child: Boolean value to indicate if the expression is a child. 73 An expression is a child if it is derived from the main 74 expression entered by the user. For example, if the user 75 entered an expression which evaluates to a struct, then 76 when exploring the fields of the struct, is_child is set 77 to True internally. 78 79 Returns: 80 No return value. 81 """ 82 type_code = value.type.code 83 if type_code in Explorer.type_code_to_explorer_map: 84 explorer_class = Explorer.type_code_to_explorer_map[type_code] 85 while explorer_class.explore_expr(expr, value, is_child): 86 pass 87 else: 88 print ("Explorer for type '%s' not yet available.\n" % 89 str(value.type)) 90 91 @staticmethod 92 def explore_type(name, datatype, is_child): 93 """Main function to explore a data type. 94 95 Arguments: 96 name: The string representing the path to the data type being 97 explored. 98 datatype: The gdb.Type value of the data type being explored. 99 is_child: Boolean value to indicate if the name is a child. 100 A name is a child if it is derived from the main name 101 entered by the user. For example, if the user entered 102 the name of struct type, then when exploring the fields 103 of the struct, is_child is set to True internally. 104 105 Returns: 106 No return value. 107 """ 108 type_code = datatype.code 109 if type_code in Explorer.type_code_to_explorer_map: 110 explorer_class = Explorer.type_code_to_explorer_map[type_code] 111 while explorer_class.explore_type(name, datatype, is_child): 112 pass 113 else: 114 print ("Explorer for type '%s' not yet available.\n" % 115 str(datatype)) 116 117 @staticmethod 118 def init_env(): 119 """Initializes the Explorer environment. 120 This function should be invoked before starting any exploration. If 121 invoked before an exploration, it need not be invoked for subsequent 122 explorations. 123 """ 124 Explorer.type_code_to_explorer_map = { 125 gdb.TYPE_CODE_CHAR : ScalarExplorer, 126 gdb.TYPE_CODE_INT : ScalarExplorer, 127 gdb.TYPE_CODE_BOOL : ScalarExplorer, 128 gdb.TYPE_CODE_FLT : ScalarExplorer, 129 gdb.TYPE_CODE_VOID : ScalarExplorer, 130 gdb.TYPE_CODE_ENUM : ScalarExplorer, 131 gdb.TYPE_CODE_STRUCT : CompoundExplorer, 132 gdb.TYPE_CODE_UNION : CompoundExplorer, 133 gdb.TYPE_CODE_PTR : PointerExplorer, 134 gdb.TYPE_CODE_REF : ReferenceExplorer, 135 gdb.TYPE_CODE_TYPEDEF : TypedefExplorer, 136 gdb.TYPE_CODE_ARRAY : ArrayExplorer 137 } 138 139 @staticmethod 140 def is_scalar_type(type): 141 """Checks whether a type is a scalar type. 142 A type is a scalar type of its type is 143 gdb.TYPE_CODE_CHAR or 144 gdb.TYPE_CODE_INT or 145 gdb.TYPE_CODE_BOOL or 146 gdb.TYPE_CODE_FLT or 147 gdb.TYPE_CODE_VOID or 148 gdb.TYPE_CODE_ENUM. 149 150 Arguments: 151 type: The type to be checked. 152 153 Returns: 154 'True' if 'type' is a scalar type. 'False' otherwise. 155 """ 156 return type.code in Explorer._SCALAR_TYPE_LIST 157 158 @staticmethod 159 def return_to_parent_value(): 160 """A utility function which prints that the current exploration session 161 is returning to the parent value. Useful when exploring values. 162 """ 163 print ("\nReturning to parent value...\n") 164 165 @staticmethod 166 def return_to_parent_value_prompt(): 167 """A utility function which prompts the user to press the 'enter' key 168 so that the exploration session can shift back to the parent value. 169 Useful when exploring values. 170 """ 171 raw_input("\nPress enter to return to parent value: ") 172 173 @staticmethod 174 def return_to_enclosing_type(): 175 """A utility function which prints that the current exploration session 176 is returning to the enclosing type. Useful when exploring types. 177 """ 178 print ("\nReturning to enclosing type...\n") 179 180 @staticmethod 181 def return_to_enclosing_type_prompt(): 182 """A utility function which prompts the user to press the 'enter' key 183 so that the exploration session can shift back to the enclosing type. 184 Useful when exploring types. 185 """ 186 raw_input("\nPress enter to return to enclosing type: ") 187 188 189 class ScalarExplorer(object): 190 """Internal class used to explore scalar values.""" 191 192 @staticmethod 193 def explore_expr(expr, value, is_child): 194 """Function to explore scalar values. 195 See Explorer.explore_expr and Explorer.is_scalar_type for more 196 information. 197 """ 198 print ("'%s' is a scalar value of type '%s'." % 199 (expr, value.type)) 200 print ("%s = %s" % (expr, str(value))) 201 202 if is_child: 203 Explorer.return_to_parent_value_prompt() 204 Explorer.return_to_parent_value() 205 206 return False 207 208 @staticmethod 209 def explore_type(name, datatype, is_child): 210 """Function to explore scalar types. 211 See Explorer.explore_type and Explorer.is_scalar_type for more 212 information. 213 """ 214 if datatype.code == gdb.TYPE_CODE_ENUM: 215 if is_child: 216 print ("%s is of an enumerated type '%s'." % 217 (name, str(datatype))) 218 else: 219 print ("'%s' is an enumerated type." % name) 220 else: 221 if is_child: 222 print ("%s is of a scalar type '%s'." % 223 (name, str(datatype))) 224 else: 225 print ("'%s' is a scalar type." % name) 226 227 if is_child: 228 Explorer.return_to_enclosing_type_prompt() 229 Explorer.return_to_enclosing_type() 230 231 return False 232 233 234 class PointerExplorer(object): 235 """Internal class used to explore pointer values.""" 236 237 @staticmethod 238 def explore_expr(expr, value, is_child): 239 """Function to explore pointer values. 240 See Explorer.explore_expr for more information. 241 """ 242 print ("'%s' is a pointer to a value of type '%s'" % 243 (expr, str(value.type.target()))) 244 option = raw_input("Continue exploring it as a pointer to a single " 245 "value [y/n]: ") 246 if option == "y": 247 deref_value = None 248 try: 249 deref_value = value.dereference() 250 str(deref_value) 251 except gdb.MemoryError: 252 print ("'%s' a pointer pointing to an invalid memory " 253 "location." % expr) 254 if is_child: 255 Explorer.return_to_parent_value_prompt() 256 return False 257 Explorer.explore_expr("*%s" % Explorer.guard_expr(expr), 258 deref_value, is_child) 259 return False 260 261 option = raw_input("Continue exploring it as a pointer to an " 262 "array [y/n]: ") 263 if option == "y": 264 while True: 265 index = 0 266 try: 267 index = int(raw_input("Enter the index of the element you " 268 "want to explore in '%s': " % expr)) 269 except ValueError: 270 break 271 element_expr = "%s[%d]" % (Explorer.guard_expr(expr), index) 272 element = value[index] 273 try: 274 str(element) 275 except gdb.MemoryError: 276 print ("Cannot read value at index %d." % index) 277 continue 278 Explorer.explore_expr(element_expr, element, True) 279 return False 280 281 if is_child: 282 Explorer.return_to_parent_value() 283 return False 284 285 @staticmethod 286 def explore_type(name, datatype, is_child): 287 """Function to explore pointer types. 288 See Explorer.explore_type for more information. 289 """ 290 target_type = datatype.target() 291 print ("\n%s is a pointer to a value of type '%s'." % 292 (name, str(target_type))) 293 294 Explorer.explore_type("the pointee type of %s" % name, 295 target_type, 296 is_child) 297 return False 298 299 300 class ReferenceExplorer(object): 301 """Internal class used to explore reference (TYPE_CODE_REF) values.""" 302 303 @staticmethod 304 def explore_expr(expr, value, is_child): 305 """Function to explore array values. 306 See Explorer.explore_expr for more information. 307 """ 308 referenced_value = value.referenced_value() 309 Explorer.explore_expr(expr, referenced_value, is_child) 310 return False 311 312 @staticmethod 313 def explore_type(name, datatype, is_child): 314 """Function to explore pointer types. 315 See Explorer.explore_type for more information. 316 """ 317 target_type = datatype.target() 318 Explorer.explore_type(name, target_type, is_child) 319 return False 320 321 322 class ArrayExplorer(object): 323 """Internal class used to explore arrays.""" 324 325 @staticmethod 326 def explore_expr(expr, value, is_child): 327 """Function to explore array values. 328 See Explorer.explore_expr for more information. 329 """ 330 target_type = value.type.target() 331 print ("'%s' is an array of '%s'." % (expr, str(target_type))) 332 index = 0 333 try: 334 index = int(raw_input("Enter the index of the element you want to " 335 "explore in '%s': " % expr)) 336 except ValueError: 337 if is_child: 338 Explorer.return_to_parent_value() 339 return False 340 341 element = None 342 try: 343 element = value[index] 344 str(element) 345 except gdb.MemoryError: 346 print ("Cannot read value at index %d." % index) 347 raw_input("Press enter to continue... ") 348 return True 349 350 Explorer.explore_expr("%s[%d]" % (Explorer.guard_expr(expr), index), 351 element, True) 352 return True 353 354 @staticmethod 355 def explore_type(name, datatype, is_child): 356 """Function to explore array types. 357 See Explorer.explore_type for more information. 358 """ 359 target_type = datatype.target() 360 print ("%s is an array of '%s'." % (name, str(target_type))) 361 362 Explorer.explore_type("the array element of %s" % name, target_type, 363 is_child) 364 return False 365 366 367 class CompoundExplorer(object): 368 """Internal class used to explore struct, classes and unions.""" 369 370 @staticmethod 371 def _print_fields(print_list): 372 """Internal function which prints the fields of a struct/class/union. 373 """ 374 max_field_name_length = 0 375 for pair in print_list: 376 if max_field_name_length < len(pair[0]): 377 max_field_name_length = len(pair[0]) 378 379 for pair in print_list: 380 print (" %*s = %s" % (max_field_name_length, pair[0], pair[1])) 381 382 @staticmethod 383 def _get_real_field_count(fields): 384 real_field_count = 0; 385 for field in fields: 386 if not field.artificial: 387 real_field_count = real_field_count + 1 388 389 return real_field_count 390 391 @staticmethod 392 def explore_expr(expr, value, is_child): 393 """Function to explore structs/classes and union values. 394 See Explorer.explore_expr for more information. 395 """ 396 datatype = value.type 397 type_code = datatype.code 398 fields = datatype.fields() 399 400 if type_code == gdb.TYPE_CODE_STRUCT: 401 type_desc = "struct/class" 402 else: 403 type_desc = "union" 404 405 if CompoundExplorer._get_real_field_count(fields) == 0: 406 print ("The value of '%s' is a %s of type '%s' with no fields." % 407 (expr, type_desc, str(value.type))) 408 if is_child: 409 Explorer.return_to_parent_value_prompt() 410 return False 411 412 print ("The value of '%s' is a %s of type '%s' with the following " 413 "fields:\n" % (expr, type_desc, str(value.type))) 414 415 has_explorable_fields = False 416 choice_to_compound_field_map = { } 417 current_choice = 0 418 print_list = [ ] 419 for field in fields: 420 if field.artificial: 421 continue 422 field_full_name = Explorer.guard_expr(expr) + "." + field.name 423 if field.is_base_class: 424 field_value = value.cast(field.type) 425 else: 426 field_value = value[field.name] 427 literal_value = "" 428 if type_code == gdb.TYPE_CODE_UNION: 429 literal_value = ("<Enter %d to explore this field of type " 430 "'%s'>" % (current_choice, str(field.type))) 431 has_explorable_fields = True 432 else: 433 if Explorer.is_scalar_type(field.type): 434 literal_value = ("%s .. (Value of type '%s')" % 435 (str(field_value), str(field.type))) 436 else: 437 if field.is_base_class: 438 field_desc = "base class" 439 else: 440 field_desc = "field" 441 literal_value = ("<Enter %d to explore this %s of type " 442 "'%s'>" % 443 (current_choice, field_desc, 444 str(field.type))) 445 has_explorable_fields = True 446 447 choice_to_compound_field_map[str(current_choice)] = ( 448 field_full_name, field_value) 449 current_choice = current_choice + 1 450 451 print_list.append((field.name, literal_value)) 452 453 CompoundExplorer._print_fields(print_list) 454 print ("") 455 456 if has_explorable_fields: 457 choice = raw_input("Enter the field number of choice: ") 458 if choice in choice_to_compound_field_map: 459 Explorer.explore_expr(choice_to_compound_field_map[choice][0], 460 choice_to_compound_field_map[choice][1], 461 True) 462 return True 463 else: 464 if is_child: 465 Explorer.return_to_parent_value() 466 else: 467 if is_child: 468 Explorer.return_to_parent_value_prompt() 469 470 return False 471 472 @staticmethod 473 def explore_type(name, datatype, is_child): 474 """Function to explore struct/class and union types. 475 See Explorer.explore_type for more information. 476 """ 477 type_code = datatype.code 478 type_desc = "" 479 if type_code == gdb.TYPE_CODE_STRUCT: 480 type_desc = "struct/class" 481 else: 482 type_desc = "union" 483 484 fields = datatype.fields() 485 if CompoundExplorer._get_real_field_count(fields) == 0: 486 if is_child: 487 print ("%s is a %s of type '%s' with no fields." % 488 (name, type_desc, str(datatype))) 489 Explorer.return_to_enclosing_type_prompt() 490 else: 491 print ("'%s' is a %s with no fields." % (name, type_desc)) 492 return False 493 494 if is_child: 495 print ("%s is a %s of type '%s' " 496 "with the following fields:\n" % 497 (name, type_desc, str(datatype))) 498 else: 499 print ("'%s' is a %s with the following " 500 "fields:\n" % 501 (name, type_desc)) 502 503 has_explorable_fields = False 504 current_choice = 0 505 choice_to_compound_field_map = { } 506 print_list = [ ] 507 for field in fields: 508 if field.artificial: 509 continue 510 if field.is_base_class: 511 field_desc = "base class" 512 else: 513 field_desc = "field" 514 rhs = ("<Enter %d to explore this %s of type '%s'>" % 515 (current_choice, field_desc, str(field.type))) 516 print_list.append((field.name, rhs)) 517 choice_to_compound_field_map[str(current_choice)] = ( 518 field.name, field.type, field_desc) 519 current_choice = current_choice + 1 520 521 CompoundExplorer._print_fields(print_list) 522 print ("") 523 524 if len(choice_to_compound_field_map) > 0: 525 choice = raw_input("Enter the field number of choice: ") 526 if choice in choice_to_compound_field_map: 527 if is_child: 528 new_name = ("%s '%s' of %s" % 529 (choice_to_compound_field_map[choice][2], 530 choice_to_compound_field_map[choice][0], 531 name)) 532 else: 533 new_name = ("%s '%s' of '%s'" % 534 (choice_to_compound_field_map[choice][2], 535 choice_to_compound_field_map[choice][0], 536 name)) 537 Explorer.explore_type(new_name, 538 choice_to_compound_field_map[choice][1], True) 539 return True 540 else: 541 if is_child: 542 Explorer.return_to_enclosing_type() 543 else: 544 if is_child: 545 Explorer.return_to_enclosing_type_prompt() 546 547 return False 548 549 550 class TypedefExplorer(object): 551 """Internal class used to explore values whose type is a typedef.""" 552 553 @staticmethod 554 def explore_expr(expr, value, is_child): 555 """Function to explore typedef values. 556 See Explorer.explore_expr for more information. 557 """ 558 actual_type = value.type.strip_typedefs() 559 print ("The value of '%s' is of type '%s' " 560 "which is a typedef of type '%s'" % 561 (expr, str(value.type), str(actual_type))) 562 563 Explorer.explore_expr(expr, value.cast(actual_type), is_child) 564 return False 565 566 @staticmethod 567 def explore_type(name, datatype, is_child): 568 """Function to explore typedef types. 569 See Explorer.explore_type for more information. 570 """ 571 actual_type = datatype.strip_typedefs() 572 if is_child: 573 print ("The type of %s is a typedef of type '%s'." % 574 (name, str(actual_type))) 575 else: 576 print ("The type '%s' is a typedef of type '%s'." % 577 (name, str(actual_type))) 578 579 Explorer.explore_type(name, actual_type, is_child) 580 return False 581 582 583 class ExploreUtils(object): 584 """Internal class which provides utilities for the main command classes.""" 585 586 @staticmethod 587 def check_args(name, arg_str): 588 """Utility to check if adequate number of arguments are passed to an 589 explore command. 590 591 Arguments: 592 name: The name of the explore command. 593 arg_str: The argument string passed to the explore command. 594 595 Returns: 596 True if adequate arguments are passed, false otherwise. 597 598 Raises: 599 gdb.GdbError if adequate arguments are not passed. 600 """ 601 if len(arg_str) < 1: 602 raise gdb.GdbError("ERROR: '%s' requires an argument." 603 % name) 604 return False 605 else: 606 return True 607 608 @staticmethod 609 def get_type_from_str(type_str): 610 """A utility function to deduce the gdb.Type value from a string 611 representing the type. 612 613 Arguments: 614 type_str: The type string from which the gdb.Type value should be 615 deduced. 616 617 Returns: 618 The deduced gdb.Type value if possible, None otherwise. 619 """ 620 try: 621 # Assume the current language to be C/C++ and make a try. 622 return gdb.parse_and_eval("(%s *)0" % type_str).type.target() 623 except RuntimeError: 624 # If assumption of current language to be C/C++ was wrong, then 625 # lookup the type using the API. 626 try: 627 return gdb.lookup_type(type_str) 628 except RuntimeError: 629 return None 630 631 @staticmethod 632 def get_value_from_str(value_str): 633 """A utility function to deduce the gdb.Value value from a string 634 representing the value. 635 636 Arguments: 637 value_str: The value string from which the gdb.Value value should 638 be deduced. 639 640 Returns: 641 The deduced gdb.Value value if possible, None otherwise. 642 """ 643 try: 644 return gdb.parse_and_eval(value_str) 645 except RuntimeError: 646 return None 647 648 649 class ExploreCommand(gdb.Command): 650 """Explore a value or a type valid in the current context. 651 652 Usage: 653 654 explore ARG 655 656 - ARG is either a valid expression or a type name. 657 - At any stage of exploration, hit the return key (instead of a 658 choice, if any) to return to the enclosing type or value. 659 """ 660 661 def __init__(self): 662 super(ExploreCommand, self).__init__(name = "explore", 663 command_class = gdb.COMMAND_DATA, 664 prefix = True) 665 666 def invoke(self, arg_str, from_tty): 667 if ExploreUtils.check_args("explore", arg_str) == False: 668 return 669 670 # Check if it is a value 671 value = ExploreUtils.get_value_from_str(arg_str) 672 if value is not None: 673 Explorer.explore_expr(arg_str, value, False) 674 return 675 676 # If it is not a value, check if it is a type 677 datatype = ExploreUtils.get_type_from_str(arg_str) 678 if datatype is not None: 679 Explorer.explore_type(arg_str, datatype, False) 680 return 681 682 # If it is neither a value nor a type, raise an error. 683 raise gdb.GdbError( 684 ("'%s' neither evaluates to a value nor is a type " 685 "in the current context." % 686 arg_str)) 687 688 689 class ExploreValueCommand(gdb.Command): 690 """Explore value of an expression valid in the current context. 691 692 Usage: 693 694 explore value ARG 695 696 - ARG is a valid expression. 697 - At any stage of exploration, hit the return key (instead of a 698 choice, if any) to return to the enclosing value. 699 """ 700 701 def __init__(self): 702 super(ExploreValueCommand, self).__init__( 703 name = "explore value", command_class = gdb.COMMAND_DATA) 704 705 def invoke(self, arg_str, from_tty): 706 if ExploreUtils.check_args("explore value", arg_str) == False: 707 return 708 709 value = ExploreUtils.get_value_from_str(arg_str) 710 if value is None: 711 raise gdb.GdbError( 712 (" '%s' does not evaluate to a value in the current " 713 "context." % 714 arg_str)) 715 return 716 717 Explorer.explore_expr(arg_str, value, False) 718 719 720 class ExploreTypeCommand(gdb.Command): 721 """Explore a type or the type of an expression valid in the current 722 context. 723 724 Usage: 725 726 explore type ARG 727 728 - ARG is a valid expression or a type name. 729 - At any stage of exploration, hit the return key (instead of a 730 choice, if any) to return to the enclosing type. 731 """ 732 733 def __init__(self): 734 super(ExploreTypeCommand, self).__init__( 735 name = "explore type", command_class = gdb.COMMAND_DATA) 736 737 def invoke(self, arg_str, from_tty): 738 if ExploreUtils.check_args("explore type", arg_str) == False: 739 return 740 741 datatype = ExploreUtils.get_type_from_str(arg_str) 742 if datatype is not None: 743 Explorer.explore_type(arg_str, datatype, False) 744 return 745 746 value = ExploreUtils.get_value_from_str(arg_str) 747 if value is not None: 748 print ("'%s' is of type '%s'." % (arg_str, str(value.type))) 749 Explorer.explore_type(str(value.type), value.type, False) 750 return 751 752 raise gdb.GdbError(("'%s' is not a type or value in the current " 753 "context." % arg_str)) 754 755 756 Explorer.init_env() 757 758 ExploreCommand() 759 ExploreValueCommand() 760 ExploreTypeCommand() 761