17"""Implementation of the GDB 'explore' command using the GDB Python API."""
24 """Internal class which invokes other explorers."""
27 type_code_to_explorer_map = {}
43 if expr[0] ==
"(" and expr[length - 1] ==
")":
51 or (
"a" <= c
and c <=
"z")
52 or (
"A" <= c
and c <=
"Z")
53 or (
"0" <= c
and c <=
"9")
62 return "(" + expr +
")"
68 """Main function to explore an expression value.
71 expr: The expression string that is being explored.
72 value: The gdb.Value value of the expression.
73 is_child: Boolean value to indicate
if the expression
is a child.
74 An expression
is a child
if it
is derived
from the main
75 expression entered by the user. For example,
if the user
76 entered an expression which evaluates to a struct, then
77 when exploring the fields of the struct, is_child
is set
83 type_code = value.type.code
84 if type_code
in Explorer.type_code_to_explorer_map:
85 explorer_class = Explorer.type_code_to_explorer_map[type_code]
86 while explorer_class.explore_expr(expr, value, is_child):
89 print(
"Explorer for type '%s' not yet available.\n" % str(value.type))
93 """Main function to explore a data type.
96 name: The string representing the path to the data type being
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.
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):
114 print(
"Explorer for type '%s' not yet available.\n" % str(datatype))
118 """Initializes the Explorer environment.
119 This function should be invoked before starting any exploration. If
120 invoked before an exploration, it need not be invoked
for subsequent
123 Explorer.type_code_to_explorer_map = {
124 gdb.TYPE_CODE_CHAR: ScalarExplorer,
125 gdb.TYPE_CODE_INT: ScalarExplorer,
126 gdb.TYPE_CODE_BOOL: ScalarExplorer,
127 gdb.TYPE_CODE_FLT: ScalarExplorer,
128 gdb.TYPE_CODE_VOID: ScalarExplorer,
129 gdb.TYPE_CODE_ENUM: ScalarExplorer,
130 gdb.TYPE_CODE_STRUCT: CompoundExplorer,
131 gdb.TYPE_CODE_UNION: CompoundExplorer,
132 gdb.TYPE_CODE_PTR: PointerExplorer,
133 gdb.TYPE_CODE_REF: ReferenceExplorer,
134 gdb.TYPE_CODE_RVALUE_REF: ReferenceExplorer,
135 gdb.TYPE_CODE_TYPEDEF: TypedefExplorer,
136 gdb.TYPE_CODE_ARRAY: ArrayExplorer,
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
145 gdb.TYPE_CODE_BOOL
or
147 gdb.TYPE_CODE_VOID
or
151 type: The type to be checked.
154 'True' if 'type' is a scalar type.
'False' otherwise.
156 return type.code
in Explorer._SCALAR_TYPE_LIST
160 """A utility function which prints that the current exploration session
161 is returning to the parent value. Useful when exploring values.
163 print("\nReturning to parent value...\n")
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.
171 input("\nPress enter to return to parent value: ")
175 """A utility function which prints that the current exploration session
176 is returning to the enclosing type. Useful when exploring types.
178 print("\nReturning to enclosing type...\n")
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.
186 input("\nPress enter to return to enclosing type: ")
190 """Internal class used to explore scalar values."""
194 """Function to explore scalar values.
195 See Explorer.explore_expr and Explorer.is_scalar_type
for more
198 print("'%s' is a scalar value of type '%s'." % (expr, value.type))
199 print(
"%s = %s" % (expr, str(value)))
202 Explorer.return_to_parent_value_prompt()
203 Explorer.return_to_parent_value()
209 """Function to explore scalar types.
210 See Explorer.explore_type and Explorer.is_scalar_type
for more
213 if datatype.code == gdb.TYPE_CODE_ENUM:
215 print(
"%s is of an enumerated type '%s'." % (name, str(datatype)))
217 print(
"'%s' is an enumerated type." % name)
220 print(
"%s is of a scalar type '%s'." % (name, str(datatype)))
222 print(
"'%s' is a scalar type." % name)
225 Explorer.return_to_enclosing_type_prompt()
226 Explorer.return_to_enclosing_type()
232 """Internal class used to explore pointer values."""
236 """Function to explore pointer values.
237 See Explorer.explore_expr for more information.
240 "'%s' is a pointer to a value of type '%s'"
241 % (expr, str(value.type.target()))
244 "Continue exploring it as a pointer to a single " "value [y/n]: "
249 deref_value = value.dereference()
251 except gdb.MemoryError:
253 "'%s' a pointer pointing to an invalid memory " "location." % expr
256 Explorer.return_to_parent_value_prompt()
258 Explorer.explore_expr(
259 "*%s" % Explorer.guard_expr(expr), deref_value, is_child
263 option = input(
"Continue exploring it as a pointer to an " "array [y/n]: ")
270 "Enter the index of the element you "
271 "want to explore in '%s': " % expr
276 element_expr =
"%s[%d]" % (Explorer.guard_expr(expr), index)
277 element = value[index]
280 except gdb.MemoryError:
281 print(
"Cannot read value at index %d." % index)
283 Explorer.explore_expr(element_expr, element,
True)
287 Explorer.return_to_parent_value()
292 """Function to explore pointer types.
293 See Explorer.explore_type for more information.
295 target_type = datatype.target()
296 print("\n%s is a pointer to a value of type '%s'." % (name, str(target_type)))
298 Explorer.explore_type(
"the pointee type of %s" % name, target_type, is_child)
303 """Internal class used to explore reference (TYPE_CODE_REF) values."""
307 """Function to explore array values.
308 See Explorer.explore_expr for more information.
310 referenced_value = value.referenced_value()
311 Explorer.explore_expr(expr, referenced_value, is_child)
316 """Function to explore pointer types.
317 See Explorer.explore_type for more information.
319 target_type = datatype.target()
320 Explorer.explore_type(name, target_type, is_child)
325 """Internal class used to explore arrays."""
329 """Function to explore array values.
330 See Explorer.explore_expr for more information.
332 target_type = value.type.target()
333 print("'%s' is an array of '%s'." % (expr, str(target_type)))
338 "Enter the index of the element you want to "
339 "explore in '%s': " % expr
344 Explorer.return_to_parent_value()
349 element = value[index]
351 except gdb.MemoryError:
352 print(
"Cannot read value at index %d." % index)
353 input(
"Press enter to continue... ")
356 Explorer.explore_expr(
357 "%s[%d]" % (Explorer.guard_expr(expr), index), element,
True
363 """Function to explore array types.
364 See Explorer.explore_type for more information.
366 target_type = datatype.target()
367 print("%s is an array of '%s'." % (name, str(target_type)))
369 Explorer.explore_type(
"the array element of %s" % name, target_type, is_child)
374 """Internal class used to explore struct, classes and unions."""
378 """Internal function which prints the fields of a struct/class/union."""
379 max_field_name_length = 0
380 for pair
in print_list:
381 if max_field_name_length < len(pair[0]):
382 max_field_name_length = len(pair[0])
384 for pair
in print_list:
385 print(
" %*s = %s" % (max_field_name_length, pair[0], pair[1]))
391 if not field.artificial:
392 real_field_count = real_field_count + 1
394 return real_field_count
398 """Function to explore structs/classes and union values.
399 See Explorer.explore_expr for more information.
401 datatype = value.type
402 type_code = datatype.code
403 fields = datatype.fields()
405 if type_code == gdb.TYPE_CODE_STRUCT:
406 type_desc =
"struct/class"
410 if CompoundExplorer._get_real_field_count(fields) == 0:
412 "The value of '%s' is a %s of type '%s' with no fields."
413 % (expr, type_desc, str(value.type))
416 Explorer.return_to_parent_value_prompt()
420 "The value of '%s' is a %s of type '%s' with the following "
421 "fields:\n" % (expr, type_desc, str(value.type))
424 has_explorable_fields =
False
425 choice_to_compound_field_map = {}
431 field_full_name = Explorer.guard_expr(expr) +
"." + field.name
432 if field.is_base_class:
433 field_value = value.cast(field.type)
435 field_value = value[field.name]
437 if type_code == gdb.TYPE_CODE_UNION:
438 literal_value =
"<Enter %d to explore this field of type " "'%s'>" % (
442 has_explorable_fields =
True
444 if Explorer.is_scalar_type(field.type):
445 literal_value =
"%s .. (Value of type '%s')" % (
450 if field.is_base_class:
451 field_desc =
"base class"
454 literal_value =
"<Enter %d to explore this %s of type " "'%s'>" % (
459 has_explorable_fields =
True
461 choice_to_compound_field_map[str(current_choice)] = (
465 current_choice = current_choice + 1
467 print_list.append((field.name, literal_value))
469 CompoundExplorer._print_fields(print_list)
472 if has_explorable_fields:
473 choice = input(
"Enter the field number of choice: ")
474 if choice
in choice_to_compound_field_map:
475 Explorer.explore_expr(
476 choice_to_compound_field_map[choice][0],
477 choice_to_compound_field_map[choice][1],
483 Explorer.return_to_parent_value()
486 Explorer.return_to_parent_value_prompt()
492 """Function to explore struct/class and union types.
493 See Explorer.explore_type for more information.
495 type_code = datatype.code
497 if type_code == gdb.TYPE_CODE_STRUCT:
498 type_desc =
"struct/class"
502 fields = datatype.fields()
503 if CompoundExplorer._get_real_field_count(fields) == 0:
506 "%s is a %s of type '%s' with no fields."
507 % (name, type_desc, str(datatype))
509 Explorer.return_to_enclosing_type_prompt()
511 print(
"'%s' is a %s with no fields." % (name, type_desc))
516 "%s is a %s of type '%s' "
517 "with the following fields:\n" % (name, type_desc, str(datatype))
520 print(
"'%s' is a %s with the following " "fields:\n" % (name, type_desc))
523 choice_to_compound_field_map = {}
528 if field.is_base_class:
529 field_desc =
"base class"
532 rhs =
"<Enter %d to explore this %s of type '%s'>" % (
537 print_list.append((field.name, rhs))
538 choice_to_compound_field_map[str(current_choice)] = (
543 current_choice = current_choice + 1
545 CompoundExplorer._print_fields(print_list)
548 if len(choice_to_compound_field_map) > 0:
549 choice = input(
"Enter the field number of choice: ")
550 if choice
in choice_to_compound_field_map:
552 new_name =
"%s '%s' of %s" % (
553 choice_to_compound_field_map[choice][2],
554 choice_to_compound_field_map[choice][0],
558 new_name =
"%s '%s' of '%s'" % (
559 choice_to_compound_field_map[choice][2],
560 choice_to_compound_field_map[choice][0],
563 Explorer.explore_type(
564 new_name, choice_to_compound_field_map[choice][1],
True
569 Explorer.return_to_enclosing_type()
572 Explorer.return_to_enclosing_type_prompt()
578 """Internal class used to explore values whose type is a typedef."""
582 """Function to explore typedef values.
583 See Explorer.explore_expr for more information.
585 actual_type = value.type.strip_typedefs()
587 "The value of '%s' is of type '%s' "
588 "which is a typedef of type '%s'"
589 % (expr, str(value.type), str(actual_type))
592 Explorer.explore_expr(expr, value.cast(actual_type), is_child)
597 """Function to explore typedef types.
598 See Explorer.explore_type for more information.
600 actual_type = datatype.strip_typedefs()
603 "The type of %s is a typedef of type '%s'." % (name, str(actual_type))
606 print(
"The type '%s' is a typedef of type '%s'." % (name, str(actual_type)))
608 Explorer.explore_type(name, actual_type, is_child)
613 """Internal class which provides utilities for the main command classes."""
617 """Utility to check if adequate number of arguments are passed to an
621 name: The name of the explore command.
622 arg_str: The argument string passed to the explore command.
625 True if adequate arguments are passed, false otherwise.
628 gdb.GdbError
if adequate arguments are
not passed.
631 raise gdb.GdbError(
"ERROR: '%s' requires an argument." % name)
638 """A utility function to deduce the gdb.Type value from a string
639 representing the type.
642 type_str: The type string from which the gdb.Type value should be
646 The deduced gdb.Type value
if possible,
None otherwise.
650 return gdb.parse_and_eval(
"(%s *)0" % type_str).type.target()
655 return gdb.lookup_type(type_str)
661 """A utility function to deduce the gdb.Value value from a string
662 representing the value.
665 value_str: The value string from which the gdb.Value value should
669 The deduced gdb.Value value
if possible,
None otherwise.
672 return gdb.parse_and_eval(value_str)
678 """Explore a value or a type valid in the current context.
682 - ARG is either a valid expression
or a type name.
683 - At any stage of exploration, hit the
return key (instead of a
684 choice,
if any) to
return to the enclosing type
or value.
"""
687 super(ExploreCommand, self).
__init__(
688 name=
"explore", command_class=gdb.COMMAND_DATA, prefix=
True
692 if ExploreUtils.check_args(
"explore", arg_str)
is False:
696 value = ExploreUtils.get_value_from_str(arg_str)
697 if value
is not None:
698 Explorer.explore_expr(arg_str, value,
False)
702 datatype = ExploreUtils.get_type_from_str(arg_str)
703 if datatype
is not None:
704 Explorer.explore_type(arg_str, datatype,
False)
710 "'%s' neither evaluates to a value nor is a type "
711 "in the current context." % arg_str
717 """Explore value of an expression valid in the current context.
719 Usage: explore value ARG
721 - ARG is a valid expression.
722 - At any stage of exploration, hit the
return key (instead of a
723 choice,
if any) to
return to the enclosing value.
"""
726 super(ExploreValueCommand, self).
__init__(
727 name=
"explore value", command_class=gdb.COMMAND_DATA
731 if ExploreUtils.check_args(
"explore value", arg_str)
is False:
734 value = ExploreUtils.get_value_from_str(arg_str)
738 " '%s' does not evaluate to a value in the current "
744 Explorer.explore_expr(arg_str, value,
False)
748 """Explore a type or the type of an expression.
750 Usage: explore type ARG
752 - ARG is a valid expression
or a type name.
753 - At any stage of exploration, hit the
return key (instead of a
754 choice,
if any) to
return to the enclosing type.
"""
757 super(ExploreTypeCommand, self).
__init__(
758 name=
"explore type", command_class=gdb.COMMAND_DATA
762 if ExploreUtils.check_args(
"explore type", arg_str)
is False:
765 datatype = ExploreUtils.get_type_from_str(arg_str)
766 if datatype
is not None:
767 Explorer.explore_type(arg_str, datatype,
False)
770 value = ExploreUtils.get_value_from_str(arg_str)
771 if value
is not None:
772 print(
"'%s' is of type '%s'." % (arg_str, str(value.type)))
773 Explorer.explore_type(str(value.type), value.type,
False)
777 (
"'%s' is not a type or value in the current " "context." % arg_str)
def explore_expr(expr, value, is_child)
def explore_type(name, datatype, is_child)
def _print_fields(print_list)
def _get_real_field_count(fields)
def explore_expr(expr, value, is_child)
def explore_type(name, datatype, is_child)
def invoke(self, arg_str, from_tty)
def invoke(self, arg_str, from_tty)
def check_args(name, arg_str)
def get_value_from_str(value_str)
def get_type_from_str(type_str)
def invoke(self, arg_str, from_tty)
def return_to_parent_value()
def explore_type(name, datatype, is_child)
def return_to_enclosing_type_prompt()
def return_to_parent_value_prompt()
def return_to_enclosing_type()
def explore_expr(expr, value, is_child)
def explore_type(name, datatype, is_child)
def explore_expr(expr, value, is_child)
def explore_type(name, datatype, is_child)
def explore_expr(expr, value, is_child)
def explore_expr(expr, value, is_child)
def explore_type(name, datatype, is_child)
def explore_type(name, datatype, is_child)
def explore_expr(expr, value, is_child)