1 # GDB 'explore' command.
2 # Copyright (C) 2012-2022 Free Software Foundation, Inc.
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.
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.
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/>.
17 """Implementation of the GDB 'explore' command using the GDB Python API."""
22 if sys
.version_info
[0] > 2:
23 # Python 3 renamed raw_input to input
27 class Explorer(object):
28 """Internal class which invokes other explorers."""
30 # This map is filled by the Explorer.init_env() function
31 type_code_to_explorer_map
= {}
47 if expr
[0] == "(" and expr
[length
- 1] == ")":
55 or ("a" <= c
and c
<= "z")
56 or ("A" <= c
and c
<= "Z")
57 or ("0" <= c
and c
<= "9")
66 return "(" + expr
+ ")"
71 def explore_expr(expr
, value
, is_child
):
72 """Main function to explore an expression value.
75 expr: The expression string that is being explored.
76 value: The gdb.Value value of the expression.
77 is_child: Boolean value to indicate if the expression is a child.
78 An expression is a child if it is derived from the main
79 expression entered by the user. For example, if the user
80 entered an expression which evaluates to a struct, then
81 when exploring the fields of the struct, is_child is set
87 type_code
= value
.type.code
88 if type_code
in Explorer
.type_code_to_explorer_map
:
89 explorer_class
= Explorer
.type_code_to_explorer_map
[type_code
]
90 while explorer_class
.explore_expr(expr
, value
, is_child
):
93 print("Explorer for type '%s' not yet available.\n" % str(value
.type))
96 def explore_type(name
, datatype
, is_child
):
97 """Main function to explore a data type.
100 name: The string representing the path to the data type being
102 datatype: The gdb.Type value of the data type being explored.
103 is_child: Boolean value to indicate if the name is a child.
104 A name is a child if it is derived from the main name
105 entered by the user. For example, if the user entered
106 the name of struct type, then when exploring the fields
107 of the struct, is_child is set to True internally.
112 type_code
= datatype
.code
113 if type_code
in Explorer
.type_code_to_explorer_map
:
114 explorer_class
= Explorer
.type_code_to_explorer_map
[type_code
]
115 while explorer_class
.explore_type(name
, datatype
, is_child
):
118 print("Explorer for type '%s' not yet available.\n" % str(datatype
))
122 """Initializes the Explorer environment.
123 This function should be invoked before starting any exploration. If
124 invoked before an exploration, it need not be invoked for subsequent
127 Explorer
.type_code_to_explorer_map
= {
128 gdb
.TYPE_CODE_CHAR
: ScalarExplorer
,
129 gdb
.TYPE_CODE_INT
: ScalarExplorer
,
130 gdb
.TYPE_CODE_BOOL
: ScalarExplorer
,
131 gdb
.TYPE_CODE_FLT
: ScalarExplorer
,
132 gdb
.TYPE_CODE_VOID
: ScalarExplorer
,
133 gdb
.TYPE_CODE_ENUM
: ScalarExplorer
,
134 gdb
.TYPE_CODE_STRUCT
: CompoundExplorer
,
135 gdb
.TYPE_CODE_UNION
: CompoundExplorer
,
136 gdb
.TYPE_CODE_PTR
: PointerExplorer
,
137 gdb
.TYPE_CODE_REF
: ReferenceExplorer
,
138 gdb
.TYPE_CODE_RVALUE_REF
: ReferenceExplorer
,
139 gdb
.TYPE_CODE_TYPEDEF
: TypedefExplorer
,
140 gdb
.TYPE_CODE_ARRAY
: ArrayExplorer
,
144 def is_scalar_type(type):
145 """Checks whether a type is a scalar type.
146 A type is a scalar type of its type is
147 gdb.TYPE_CODE_CHAR or
149 gdb.TYPE_CODE_BOOL or
151 gdb.TYPE_CODE_VOID or
155 type: The type to be checked.
158 'True' if 'type' is a scalar type. 'False' otherwise.
160 return type.code
in Explorer
._SCALAR
_TYPE
_LIST
163 def return_to_parent_value():
164 """A utility function which prints that the current exploration session
165 is returning to the parent value. Useful when exploring values.
167 print("\nReturning to parent value...\n")
170 def return_to_parent_value_prompt():
171 """A utility function which prompts the user to press the 'enter' key
172 so that the exploration session can shift back to the parent value.
173 Useful when exploring values.
175 raw_input("\nPress enter to return to parent value: ")
178 def return_to_enclosing_type():
179 """A utility function which prints that the current exploration session
180 is returning to the enclosing type. Useful when exploring types.
182 print("\nReturning to enclosing type...\n")
185 def return_to_enclosing_type_prompt():
186 """A utility function which prompts the user to press the 'enter' key
187 so that the exploration session can shift back to the enclosing type.
188 Useful when exploring types.
190 raw_input("\nPress enter to return to enclosing type: ")
193 class ScalarExplorer(object):
194 """Internal class used to explore scalar values."""
197 def explore_expr(expr
, value
, is_child
):
198 """Function to explore scalar values.
199 See Explorer.explore_expr and Explorer.is_scalar_type for more
202 print("'%s' is a scalar value of type '%s'." % (expr
, value
.type))
203 print("%s = %s" % (expr
, str(value
)))
206 Explorer
.return_to_parent_value_prompt()
207 Explorer
.return_to_parent_value()
212 def explore_type(name
, datatype
, is_child
):
213 """Function to explore scalar types.
214 See Explorer.explore_type and Explorer.is_scalar_type for more
217 if datatype
.code
== gdb
.TYPE_CODE_ENUM
:
219 print("%s is of an enumerated type '%s'." % (name
, str(datatype
)))
221 print("'%s' is an enumerated type." % name
)
224 print("%s is of a scalar type '%s'." % (name
, str(datatype
)))
226 print("'%s' is a scalar type." % name
)
229 Explorer
.return_to_enclosing_type_prompt()
230 Explorer
.return_to_enclosing_type()
235 class PointerExplorer(object):
236 """Internal class used to explore pointer values."""
239 def explore_expr(expr
, value
, is_child
):
240 """Function to explore pointer values.
241 See Explorer.explore_expr for more information.
244 "'%s' is a pointer to a value of type '%s'"
245 % (expr
, str(value
.type.target()))
248 "Continue exploring it as a pointer to a single " "value [y/n]: "
253 deref_value
= value
.dereference()
255 except gdb
.MemoryError:
257 "'%s' a pointer pointing to an invalid memory " "location." % expr
260 Explorer
.return_to_parent_value_prompt()
262 Explorer
.explore_expr(
263 "*%s" % Explorer
.guard_expr(expr
), deref_value
, is_child
267 option
= raw_input("Continue exploring it as a pointer to an " "array [y/n]: ")
274 "Enter the index of the element you "
275 "want to explore in '%s': " % expr
280 element_expr
= "%s[%d]" % (Explorer
.guard_expr(expr
), index
)
281 element
= value
[index
]
284 except gdb
.MemoryError:
285 print("Cannot read value at index %d." % index
)
287 Explorer
.explore_expr(element_expr
, element
, True)
291 Explorer
.return_to_parent_value()
295 def explore_type(name
, datatype
, is_child
):
296 """Function to explore pointer types.
297 See Explorer.explore_type for more information.
299 target_type
= datatype
.target()
300 print("\n%s is a pointer to a value of type '%s'." % (name
, str(target_type
)))
302 Explorer
.explore_type("the pointee type of %s" % name
, target_type
, is_child
)
306 class ReferenceExplorer(object):
307 """Internal class used to explore reference (TYPE_CODE_REF) values."""
310 def explore_expr(expr
, value
, is_child
):
311 """Function to explore array values.
312 See Explorer.explore_expr for more information.
314 referenced_value
= value
.referenced_value()
315 Explorer
.explore_expr(expr
, referenced_value
, is_child
)
319 def explore_type(name
, datatype
, is_child
):
320 """Function to explore pointer types.
321 See Explorer.explore_type for more information.
323 target_type
= datatype
.target()
324 Explorer
.explore_type(name
, target_type
, is_child
)
328 class ArrayExplorer(object):
329 """Internal class used to explore arrays."""
332 def explore_expr(expr
, value
, is_child
):
333 """Function to explore array values.
334 See Explorer.explore_expr for more information.
336 target_type
= value
.type.target()
337 print("'%s' is an array of '%s'." % (expr
, str(target_type
)))
342 "Enter the index of the element you want to "
343 "explore in '%s': " % expr
348 Explorer
.return_to_parent_value()
353 element
= value
[index
]
355 except gdb
.MemoryError:
356 print("Cannot read value at index %d." % index
)
357 raw_input("Press enter to continue... ")
360 Explorer
.explore_expr(
361 "%s[%d]" % (Explorer
.guard_expr(expr
), index
), element
, True
366 def explore_type(name
, datatype
, is_child
):
367 """Function to explore array types.
368 See Explorer.explore_type for more information.
370 target_type
= datatype
.target()
371 print("%s is an array of '%s'." % (name
, str(target_type
)))
373 Explorer
.explore_type("the array element of %s" % name
, target_type
, is_child
)
377 class CompoundExplorer(object):
378 """Internal class used to explore struct, classes and unions."""
381 def _print_fields(print_list
):
382 """Internal function which prints the fields of a struct/class/union."""
383 max_field_name_length
= 0
384 for pair
in print_list
:
385 if max_field_name_length
< len(pair
[0]):
386 max_field_name_length
= len(pair
[0])
388 for pair
in print_list
:
389 print(" %*s = %s" % (max_field_name_length
, pair
[0], pair
[1]))
392 def _get_real_field_count(fields
):
395 if not field
.artificial
:
396 real_field_count
= real_field_count
+ 1
398 return real_field_count
401 def explore_expr(expr
, value
, is_child
):
402 """Function to explore structs/classes and union values.
403 See Explorer.explore_expr for more information.
405 datatype
= value
.type
406 type_code
= datatype
.code
407 fields
= datatype
.fields()
409 if type_code
== gdb
.TYPE_CODE_STRUCT
:
410 type_desc
= "struct/class"
414 if CompoundExplorer
._get
_real
_field
_count
(fields
) == 0:
416 "The value of '%s' is a %s of type '%s' with no fields."
417 % (expr
, type_desc
, str(value
.type))
420 Explorer
.return_to_parent_value_prompt()
424 "The value of '%s' is a %s of type '%s' with the following "
425 "fields:\n" % (expr
, type_desc
, str(value
.type))
428 has_explorable_fields
= False
429 choice_to_compound_field_map
= {}
435 field_full_name
= Explorer
.guard_expr(expr
) + "." + field
.name
436 if field
.is_base_class
:
437 field_value
= value
.cast(field
.type)
439 field_value
= value
[field
.name
]
441 if type_code
== gdb
.TYPE_CODE_UNION
:
442 literal_value
= "<Enter %d to explore this field of type " "'%s'>" % (
446 has_explorable_fields
= True
448 if Explorer
.is_scalar_type(field
.type):
449 literal_value
= "%s .. (Value of type '%s')" % (
454 if field
.is_base_class
:
455 field_desc
= "base class"
458 literal_value
= "<Enter %d to explore this %s of type " "'%s'>" % (
463 has_explorable_fields
= True
465 choice_to_compound_field_map
[str(current_choice
)] = (
469 current_choice
= current_choice
+ 1
471 print_list
.append((field
.name
, literal_value
))
473 CompoundExplorer
._print
_fields
(print_list
)
476 if has_explorable_fields
:
477 choice
= raw_input("Enter the field number of choice: ")
478 if choice
in choice_to_compound_field_map
:
479 Explorer
.explore_expr(
480 choice_to_compound_field_map
[choice
][0],
481 choice_to_compound_field_map
[choice
][1],
487 Explorer
.return_to_parent_value()
490 Explorer
.return_to_parent_value_prompt()
495 def explore_type(name
, datatype
, is_child
):
496 """Function to explore struct/class and union types.
497 See Explorer.explore_type for more information.
499 type_code
= datatype
.code
501 if type_code
== gdb
.TYPE_CODE_STRUCT
:
502 type_desc
= "struct/class"
506 fields
= datatype
.fields()
507 if CompoundExplorer
._get
_real
_field
_count
(fields
) == 0:
510 "%s is a %s of type '%s' with no fields."
511 % (name
, type_desc
, str(datatype
))
513 Explorer
.return_to_enclosing_type_prompt()
515 print("'%s' is a %s with no fields." % (name
, type_desc
))
520 "%s is a %s of type '%s' "
521 "with the following fields:\n" % (name
, type_desc
, str(datatype
))
524 print("'%s' is a %s with the following " "fields:\n" % (name
, type_desc
))
526 has_explorable_fields
= False
528 choice_to_compound_field_map
= {}
533 if field
.is_base_class
:
534 field_desc
= "base class"
537 rhs
= "<Enter %d to explore this %s of type '%s'>" % (
542 print_list
.append((field
.name
, rhs
))
543 choice_to_compound_field_map
[str(current_choice
)] = (
548 current_choice
= current_choice
+ 1
550 CompoundExplorer
._print
_fields
(print_list
)
553 if len(choice_to_compound_field_map
) > 0:
554 choice
= raw_input("Enter the field number of choice: ")
555 if choice
in choice_to_compound_field_map
:
557 new_name
= "%s '%s' of %s" % (
558 choice_to_compound_field_map
[choice
][2],
559 choice_to_compound_field_map
[choice
][0],
563 new_name
= "%s '%s' of '%s'" % (
564 choice_to_compound_field_map
[choice
][2],
565 choice_to_compound_field_map
[choice
][0],
568 Explorer
.explore_type(
569 new_name
, choice_to_compound_field_map
[choice
][1], True
574 Explorer
.return_to_enclosing_type()
577 Explorer
.return_to_enclosing_type_prompt()
582 class TypedefExplorer(object):
583 """Internal class used to explore values whose type is a typedef."""
586 def explore_expr(expr
, value
, is_child
):
587 """Function to explore typedef values.
588 See Explorer.explore_expr for more information.
590 actual_type
= value
.type.strip_typedefs()
592 "The value of '%s' is of type '%s' "
593 "which is a typedef of type '%s'"
594 % (expr
, str(value
.type), str(actual_type
))
597 Explorer
.explore_expr(expr
, value
.cast(actual_type
), is_child
)
601 def explore_type(name
, datatype
, is_child
):
602 """Function to explore typedef types.
603 See Explorer.explore_type for more information.
605 actual_type
= datatype
.strip_typedefs()
608 "The type of %s is a typedef of type '%s'." % (name
, str(actual_type
))
611 print("The type '%s' is a typedef of type '%s'." % (name
, str(actual_type
)))
613 Explorer
.explore_type(name
, actual_type
, is_child
)
617 class ExploreUtils(object):
618 """Internal class which provides utilities for the main command classes."""
621 def check_args(name
, arg_str
):
622 """Utility to check if adequate number of arguments are passed to an
626 name: The name of the explore command.
627 arg_str: The argument string passed to the explore command.
630 True if adequate arguments are passed, false otherwise.
633 gdb.GdbError if adequate arguments are not passed.
636 raise gdb
.GdbError("ERROR: '%s' requires an argument." % name
)
642 def get_type_from_str(type_str
):
643 """A utility function to deduce the gdb.Type value from a string
644 representing the type.
647 type_str: The type string from which the gdb.Type value should be
651 The deduced gdb.Type value if possible, None otherwise.
654 # Assume the current language to be C/C++ and make a try.
655 return gdb
.parse_and_eval("(%s *)0" % type_str
).type.target()
657 # If assumption of current language to be C/C++ was wrong, then
658 # lookup the type using the API.
660 return gdb
.lookup_type(type_str
)
665 def get_value_from_str(value_str
):
666 """A utility function to deduce the gdb.Value value from a string
667 representing the value.
670 value_str: The value string from which the gdb.Value value should
674 The deduced gdb.Value value if possible, None otherwise.
677 return gdb
.parse_and_eval(value_str
)
682 class ExploreCommand(gdb
.Command
):
683 """Explore a value or a type valid in the current context.
687 - ARG is either a valid expression or a type name.
688 - At any stage of exploration, hit the return key (instead of a
689 choice, if any) to return to the enclosing type or value."""
692 super(ExploreCommand
, self
).__init
__(
693 name
="explore", command_class
=gdb
.COMMAND_DATA
, prefix
=True
696 def invoke(self
, arg_str
, from_tty
):
697 if ExploreUtils
.check_args("explore", arg_str
) == False:
700 # Check if it is a value
701 value
= ExploreUtils
.get_value_from_str(arg_str
)
702 if value
is not None:
703 Explorer
.explore_expr(arg_str
, value
, False)
706 # If it is not a value, check if it is a type
707 datatype
= ExploreUtils
.get_type_from_str(arg_str
)
708 if datatype
is not None:
709 Explorer
.explore_type(arg_str
, datatype
, False)
712 # If it is neither a value nor a type, raise an error.
715 "'%s' neither evaluates to a value nor is a type "
716 "in the current context." % arg_str
721 class ExploreValueCommand(gdb
.Command
):
722 """Explore value of an expression valid in the current context.
724 Usage: explore value ARG
726 - ARG is a valid expression.
727 - At any stage of exploration, hit the return key (instead of a
728 choice, if any) to return to the enclosing value."""
731 super(ExploreValueCommand
, self
).__init
__(
732 name
="explore value", command_class
=gdb
.COMMAND_DATA
735 def invoke(self
, arg_str
, from_tty
):
736 if ExploreUtils
.check_args("explore value", arg_str
) == False:
739 value
= ExploreUtils
.get_value_from_str(arg_str
)
743 " '%s' does not evaluate to a value in the current "
749 Explorer
.explore_expr(arg_str
, value
, False)
752 class ExploreTypeCommand(gdb
.Command
):
753 """Explore a type or the type of an expression.
755 Usage: explore type ARG
757 - ARG is a valid expression or a type name.
758 - At any stage of exploration, hit the return key (instead of a
759 choice, if any) to return to the enclosing type."""
762 super(ExploreTypeCommand
, self
).__init
__(
763 name
="explore type", command_class
=gdb
.COMMAND_DATA
766 def invoke(self
, arg_str
, from_tty
):
767 if ExploreUtils
.check_args("explore type", arg_str
) == False:
770 datatype
= ExploreUtils
.get_type_from_str(arg_str
)
771 if datatype
is not None:
772 Explorer
.explore_type(arg_str
, datatype
, False)
775 value
= ExploreUtils
.get_value_from_str(arg_str
)
776 if value
is not None:
777 print("'%s' is of type '%s'." % (arg_str
, str(value
.type)))
778 Explorer
.explore_type(str(value
.type), value
.type, False)
782 ("'%s' is not a type or value in the current " "context." % arg_str
)
789 ExploreValueCommand()