| Index: gdb/python/lib/gdb/command/explore.py
|
| diff --git a/gdb/python/lib/gdb/command/explore.py b/gdb/python/lib/gdb/command/explore.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..aad36717f8fb72469921709aafd18db23994bd51
|
| --- /dev/null
|
| +++ b/gdb/python/lib/gdb/command/explore.py
|
| @@ -0,0 +1,755 @@
|
| +# GDB 'explore' command.
|
| +# Copyright (C) 2012 Free Software Foundation, Inc.
|
| +
|
| +# This program is free software; you can redistribute it and/or modify
|
| +# it under the terms of the GNU General Public License as published by
|
| +# the Free Software Foundation; either version 3 of the License, or
|
| +# (at your option) any later version.
|
| +#
|
| +# This program is distributed in the hope that it will be useful,
|
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| +# GNU General Public License for more details.
|
| +#
|
| +# You should have received a copy of the GNU General Public License
|
| +# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
| +
|
| +"""Implementation of the GDB 'explore' command using the GDB Python API."""
|
| +
|
| +import gdb
|
| +
|
| +class Explorer(object):
|
| + """Internal class which invokes other explorers."""
|
| +
|
| + # This map is filled by the Explorer.init_env() function
|
| + type_code_to_explorer_map = { }
|
| +
|
| + _SCALAR_TYPE_LIST = (
|
| + gdb.TYPE_CODE_CHAR,
|
| + gdb.TYPE_CODE_INT,
|
| + gdb.TYPE_CODE_BOOL,
|
| + gdb.TYPE_CODE_FLT,
|
| + gdb.TYPE_CODE_VOID,
|
| + gdb.TYPE_CODE_ENUM,
|
| + )
|
| +
|
| + @staticmethod
|
| + def guard_expr(expr):
|
| + length = len(expr)
|
| + guard = False
|
| +
|
| + if expr[0] == '(' and expr[length-1] == ')':
|
| + pass
|
| + else:
|
| + i = 0
|
| + while i < length:
|
| + c = expr[i]
|
| + if (c == '_' or ('a' <= c and c <= 'z') or
|
| + ('A' <= c and c <= 'Z') or ('0' <= c and c <= '9')):
|
| + pass
|
| + else:
|
| + guard = True
|
| + break
|
| + i += 1
|
| +
|
| + if guard:
|
| + return "(" + expr + ")"
|
| + else:
|
| + return expr
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Main function to explore an expression value.
|
| +
|
| + Arguments:
|
| + expr: The expression string that is being explored.
|
| + value: The gdb.Value value of the expression.
|
| + is_child: Boolean value to indicate if the expression is a child.
|
| + An expression is a child if it is derived from the main
|
| + expression entered by the user. For example, if the user
|
| + entered an expression which evaluates to a struct, then
|
| + when exploring the fields of the struct, is_child is set
|
| + to True internally.
|
| +
|
| + Returns:
|
| + No return value.
|
| + """
|
| + type_code = value.type.code
|
| + if type_code in Explorer.type_code_to_explorer_map:
|
| + explorer_class = Explorer.type_code_to_explorer_map[type_code]
|
| + while explorer_class.explore_expr(expr, value, is_child):
|
| + pass
|
| + else:
|
| + print ("Explorer for type '%s' not yet available.\n" %
|
| + str(value.type))
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Main function to explore a data type.
|
| +
|
| + Arguments:
|
| + name: The string representing the path to the data type being
|
| + explored.
|
| + datatype: The gdb.Type value of the data type being explored.
|
| + is_child: Boolean value to indicate if the name is a child.
|
| + A name is a child if it is derived from the main name
|
| + entered by the user. For example, if the user entered
|
| + the name of struct type, then when exploring the fields
|
| + of the struct, is_child is set to True internally.
|
| +
|
| + Returns:
|
| + No return value.
|
| + """
|
| + type_code = datatype.code
|
| + if type_code in Explorer.type_code_to_explorer_map:
|
| + explorer_class = Explorer.type_code_to_explorer_map[type_code]
|
| + while explorer_class.explore_type(name, datatype, is_child):
|
| + pass
|
| + else:
|
| + print ("Explorer for type '%s' not yet available.\n" %
|
| + str(datatype))
|
| +
|
| + @staticmethod
|
| + def init_env():
|
| + """Initializes the Explorer environment.
|
| + This function should be invoked before starting any exploration. If
|
| + invoked before an exploration, it need not be invoked for subsequent
|
| + explorations.
|
| + """
|
| + Explorer.type_code_to_explorer_map = {
|
| + gdb.TYPE_CODE_CHAR : ScalarExplorer,
|
| + gdb.TYPE_CODE_INT : ScalarExplorer,
|
| + gdb.TYPE_CODE_BOOL : ScalarExplorer,
|
| + gdb.TYPE_CODE_FLT : ScalarExplorer,
|
| + gdb.TYPE_CODE_VOID : ScalarExplorer,
|
| + gdb.TYPE_CODE_ENUM : ScalarExplorer,
|
| + gdb.TYPE_CODE_STRUCT : CompoundExplorer,
|
| + gdb.TYPE_CODE_UNION : CompoundExplorer,
|
| + gdb.TYPE_CODE_PTR : PointerExplorer,
|
| + gdb.TYPE_CODE_REF : ReferenceExplorer,
|
| + gdb.TYPE_CODE_TYPEDEF : TypedefExplorer,
|
| + gdb.TYPE_CODE_ARRAY : ArrayExplorer
|
| + }
|
| +
|
| + @staticmethod
|
| + def is_scalar_type(type):
|
| + """Checks whether a type is a scalar type.
|
| + A type is a scalar type of its type is
|
| + gdb.TYPE_CODE_CHAR or
|
| + gdb.TYPE_CODE_INT or
|
| + gdb.TYPE_CODE_BOOL or
|
| + gdb.TYPE_CODE_FLT or
|
| + gdb.TYPE_CODE_VOID or
|
| + gdb.TYPE_CODE_ENUM.
|
| +
|
| + Arguments:
|
| + type: The type to be checked.
|
| +
|
| + Returns:
|
| + 'True' if 'type' is a scalar type. 'False' otherwise.
|
| + """
|
| + return type.code in Explorer._SCALAR_TYPE_LIST
|
| +
|
| + @staticmethod
|
| + def return_to_parent_value():
|
| + """A utility function which prints that the current exploration session
|
| + is returning to the parent value. Useful when exploring values.
|
| + """
|
| + print "\nReturning to parent value...\n"
|
| +
|
| + @staticmethod
|
| + def return_to_parent_value_prompt():
|
| + """A utility function which prompts the user to press the 'enter' key
|
| + so that the exploration session can shift back to the parent value.
|
| + Useful when exploring values.
|
| + """
|
| + raw_input("\nPress enter to return to parent value: ")
|
| +
|
| + @staticmethod
|
| + def return_to_enclosing_type():
|
| + """A utility function which prints that the current exploration session
|
| + is returning to the enclosing type. Useful when exploring types.
|
| + """
|
| + print "\nReturning to enclosing type...\n"
|
| +
|
| + @staticmethod
|
| + def return_to_enclosing_type_prompt():
|
| + """A utility function which prompts the user to press the 'enter' key
|
| + so that the exploration session can shift back to the enclosing type.
|
| + Useful when exploring types.
|
| + """
|
| + raw_input("\nPress enter to return to enclosing type: ")
|
| +
|
| +
|
| +class ScalarExplorer(object):
|
| + """Internal class used to explore scalar values."""
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore scalar values.
|
| + See Explorer.explore_expr and Explorer.is_scalar_type for more
|
| + information.
|
| + """
|
| + print ("'%s' is a scalar value of type '%s'." %
|
| + (expr, value.type))
|
| + print "%s = %s" % (expr, str(value))
|
| +
|
| + if is_child:
|
| + Explorer.return_to_parent_value_prompt()
|
| + Explorer.return_to_parent_value()
|
| +
|
| + return False
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore scalar types.
|
| + See Explorer.explore_type and Explorer.is_scalar_type for more
|
| + information.
|
| + """
|
| + if datatype.code == gdb.TYPE_CODE_ENUM:
|
| + if is_child:
|
| + print ("%s is of an enumerated type '%s'." %
|
| + (name, str(datatype)))
|
| + else:
|
| + print "'%s' is an enumerated type." % name
|
| + else:
|
| + if is_child:
|
| + print ("%s is of a scalar type '%s'." %
|
| + (name, str(datatype)))
|
| + else:
|
| + print "'%s' is a scalar type." % name
|
| +
|
| + if is_child:
|
| + Explorer.return_to_enclosing_type_prompt()
|
| + Explorer.return_to_enclosing_type()
|
| +
|
| + return False
|
| +
|
| +
|
| +class PointerExplorer(object):
|
| + """Internal class used to explore pointer values."""
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore pointer values.
|
| + See Explorer.explore_expr for more information.
|
| + """
|
| + print ("'%s' is a pointer to a value of type '%s'" %
|
| + (expr, str(value.type.target())))
|
| + option = raw_input("Continue exploring it as a pointer to a single "
|
| + "value [y/n]: ")
|
| + if option == "y":
|
| + deref_value = None
|
| + try:
|
| + deref_value = value.dereference()
|
| + str(deref_value)
|
| + except gdb.MemoryError:
|
| + print ("'%s' a pointer pointing to an invalid memory "
|
| + "location." % expr)
|
| + if is_child:
|
| + Explorer.return_to_parent_value_prompt()
|
| + return False
|
| + Explorer.explore_expr("*%s" % Explorer.guard_expr(expr),
|
| + deref_value, is_child)
|
| + return False
|
| +
|
| + option = raw_input("Continue exploring it as a pointer to an "
|
| + "array [y/n]: ")
|
| + if option == "y":
|
| + while True:
|
| + index = 0
|
| + try:
|
| + index = int(raw_input("Enter the index of the element you "
|
| + "want to explore in '%s': " % expr))
|
| + except ValueError:
|
| + break
|
| + element_expr = "%s[%d]" % (Explorer.guard_expr(expr), index)
|
| + element = value[index]
|
| + try:
|
| + str(element)
|
| + except gdb.MemoryError:
|
| + print "Cannot read value at index %d." % index
|
| + continue
|
| + Explorer.explore_expr(element_expr, element, True)
|
| + return False
|
| +
|
| + if is_child:
|
| + Explorer.return_to_parent_value()
|
| + return False
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore pointer types.
|
| + See Explorer.explore_type for more information.
|
| + """
|
| + target_type = datatype.target()
|
| + print ("\n%s is a pointer to a value of type '%s'." %
|
| + (name, str(target_type)))
|
| +
|
| + Explorer.explore_type("the pointee type of %s" % name,
|
| + target_type,
|
| + is_child)
|
| + return False
|
| +
|
| +
|
| +class ReferenceExplorer(object):
|
| + """Internal class used to explore reference (TYPE_CODE_REF) values."""
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore array values.
|
| + See Explorer.explore_expr for more information.
|
| + """
|
| + referenced_value = value.referenced_value()
|
| + Explorer.explore_expr(expr, referenced_value, is_child)
|
| + return False
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore pointer types.
|
| + See Explorer.explore_type for more information.
|
| + """
|
| + target_type = datatype.target()
|
| + Explorer.explore_type(name, target_type, is_child)
|
| + return False
|
| +
|
| +
|
| +class ArrayExplorer(object):
|
| + """Internal class used to explore arrays."""
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore array values.
|
| + See Explorer.explore_expr for more information.
|
| + """
|
| + target_type = value.type.target()
|
| + print ("'%s' is an array of '%s'." % (expr, str(target_type)))
|
| + index = 0
|
| + try:
|
| + index = int(raw_input("Enter the index of the element you want to "
|
| + "explore in '%s': " % expr))
|
| + except ValueError:
|
| + if is_child:
|
| + Explorer.return_to_parent_value()
|
| + return False
|
| +
|
| + element = None
|
| + try:
|
| + element = value[index]
|
| + str(element)
|
| + except gdb.MemoryError:
|
| + print "Cannot read value at index %d." % index
|
| + raw_input("Press enter to continue... ")
|
| + return True
|
| +
|
| + Explorer.explore_expr("%s[%d]" % (Explorer.guard_expr(expr), index),
|
| + element, True)
|
| + return True
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore array types.
|
| + See Explorer.explore_type for more information.
|
| + """
|
| + target_type = datatype.target()
|
| + print "%s is an array of '%s'." % (name, str(target_type))
|
| +
|
| + Explorer.explore_type("the array element of %s" % name, target_type,
|
| + is_child)
|
| + return False
|
| +
|
| +
|
| +class CompoundExplorer(object):
|
| + """Internal class used to explore struct, classes and unions."""
|
| +
|
| + @staticmethod
|
| + def _print_fields(print_list):
|
| + """Internal function which prints the fields of a struct/class/union.
|
| + """
|
| + max_field_name_length = 0
|
| + for pair in print_list:
|
| + if max_field_name_length < len(pair[0]):
|
| + max_field_name_length = len(pair[0])
|
| +
|
| + format_str = " {0:>%d} = {1}" % max_field_name_length
|
| + for pair in print_list:
|
| + print format_str.format(pair[0], pair[1])
|
| +
|
| + @staticmethod
|
| + def _get_real_field_count(fields):
|
| + real_field_count = 0;
|
| + for field in fields:
|
| + if not field.artificial:
|
| + real_field_count = real_field_count + 1
|
| +
|
| + return real_field_count
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore structs/classes and union values.
|
| + See Explorer.explore_expr for more information.
|
| + """
|
| + datatype = value.type
|
| + type_code = datatype.code
|
| + fields = datatype.fields()
|
| +
|
| + if type_code == gdb.TYPE_CODE_STRUCT:
|
| + type_desc = "struct/class"
|
| + else:
|
| + type_desc = "union"
|
| +
|
| + if CompoundExplorer._get_real_field_count(fields) == 0:
|
| + print ("The value of '%s' is a %s of type '%s' with no fields." %
|
| + (expr, type_desc, str(value.type)))
|
| + if is_child:
|
| + Explorer.return_to_parent_value_prompt()
|
| + return False
|
| +
|
| + print ("The value of '%s' is a %s of type '%s' with the following "
|
| + "fields:\n" % (expr, type_desc, str(value.type)))
|
| +
|
| + has_explorable_fields = False
|
| + choice_to_compound_field_map = { }
|
| + current_choice = 0
|
| + print_list = [ ]
|
| + for field in fields:
|
| + if field.artificial:
|
| + continue
|
| + field_full_name = Explorer.guard_expr(expr) + "." + field.name
|
| + if field.is_base_class:
|
| + field_value = value.cast(field.type)
|
| + else:
|
| + field_value = value[field.name]
|
| + literal_value = ""
|
| + if type_code == gdb.TYPE_CODE_UNION:
|
| + literal_value = ("<Enter %d to explore this field of type "
|
| + "'%s'>" % (current_choice, str(field.type)))
|
| + has_explorable_fields = True
|
| + else:
|
| + if Explorer.is_scalar_type(field.type):
|
| + literal_value = ("%s .. (Value of type '%s')" %
|
| + (str(field_value), str(field.type)))
|
| + else:
|
| + if field.is_base_class:
|
| + field_desc = "base class"
|
| + else:
|
| + field_desc = "field"
|
| + literal_value = ("<Enter %d to explore this %s of type "
|
| + "'%s'>" %
|
| + (current_choice, field_desc,
|
| + str(field.type)))
|
| + has_explorable_fields = True
|
| +
|
| + choice_to_compound_field_map[str(current_choice)] = (
|
| + field_full_name, field_value)
|
| + current_choice = current_choice + 1
|
| +
|
| + print_list.append((field.name, literal_value))
|
| +
|
| + CompoundExplorer._print_fields(print_list)
|
| + print ""
|
| +
|
| + if has_explorable_fields:
|
| + choice = raw_input("Enter the field number of choice: ")
|
| + if choice in choice_to_compound_field_map:
|
| + Explorer.explore_expr(choice_to_compound_field_map[choice][0],
|
| + choice_to_compound_field_map[choice][1],
|
| + True)
|
| + return True
|
| + else:
|
| + if is_child:
|
| + Explorer.returning_to_parent_value_message()
|
| + else:
|
| + if is_child:
|
| + Explorer.return_to_parent_value_prompt()
|
| +
|
| + return False
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore struct/class and union types.
|
| + See Explorer.explore_type for more information.
|
| + """
|
| + type_code = datatype.code
|
| + type_desc = ""
|
| + if type_code == gdb.TYPE_CODE_STRUCT:
|
| + type_desc = "struct/class"
|
| + else:
|
| + type_desc = "union"
|
| +
|
| + fields = datatype.fields()
|
| + if CompoundExplorer._get_real_field_count(fields) == 0:
|
| + if is_child:
|
| + print ("%s is a %s of type '%s' with no fields." %
|
| + (name, type_desc, str(datatype)))
|
| + Explorer.return_to_enclosing_type_prompt()
|
| + else:
|
| + print "'%s' is a %s with no fields." % (name, type_desc)
|
| + return False
|
| +
|
| + if is_child:
|
| + print ("%s is a %s of type '%s' "
|
| + "with the following fields:\n" %
|
| + (name, type_desc, str(datatype)))
|
| + else:
|
| + print ("'%s' is a %s with the following "
|
| + "fields:\n" %
|
| + (name, type_desc))
|
| +
|
| + has_explorable_fields = False
|
| + current_choice = 0
|
| + choice_to_compound_field_map = { }
|
| + print_list = [ ]
|
| + for field in fields:
|
| + if field.artificial:
|
| + continue
|
| + if field.is_base_class:
|
| + field_desc = "base class"
|
| + else:
|
| + field_desc = "field"
|
| + rhs = ("<Enter %d to explore this %s of type '%s'>" %
|
| + (current_choice, field_desc, str(field.type)))
|
| + print_list.append((field.name, rhs))
|
| + choice_to_compound_field_map[str(current_choice)] = (
|
| + field.name, field.type, field_desc)
|
| + current_choice = current_choice + 1
|
| +
|
| + CompoundExplorer._print_fields(print_list)
|
| + print ""
|
| +
|
| + if len(choice_to_compound_field_map) > 0:
|
| + choice = raw_input("Enter the field number of choice: ")
|
| + if choice in choice_to_compound_field_map:
|
| + if is_child:
|
| + new_name = ("%s '%s' of %s" %
|
| + (choice_to_compound_field_map[choice][2],
|
| + choice_to_compound_field_map[choice][0],
|
| + name))
|
| + else:
|
| + new_name = ("%s '%s' of '%s'" %
|
| + (choice_to_compound_field_map[choice][2],
|
| + choice_to_compound_field_map[choice][0],
|
| + name))
|
| + Explorer.explore_type(new_name,
|
| + choice_to_compound_field_map[choice][1], True)
|
| + return True
|
| + else:
|
| + if is_child:
|
| + Explorer.return_to_enclosing_type()
|
| + else:
|
| + if is_child:
|
| + Explorer.return_to_enclosing_type_prompt()
|
| +
|
| + return False
|
| +
|
| +
|
| +class TypedefExplorer(object):
|
| + """Internal class used to explore values whose type is a typedef."""
|
| +
|
| + @staticmethod
|
| + def explore_expr(expr, value, is_child):
|
| + """Function to explore typedef values.
|
| + See Explorer.explore_expr for more information.
|
| + """
|
| + actual_type = value.type.strip_typedefs()
|
| + print ("The value of '%s' is of type '%s' "
|
| + "which is a typedef of type '%s'" %
|
| + (expr, str(value.type), str(actual_type)))
|
| +
|
| + Explorer.explore_expr(expr, value.cast(actual_type), is_child)
|
| + return False
|
| +
|
| + @staticmethod
|
| + def explore_type(name, datatype, is_child):
|
| + """Function to explore typedef types.
|
| + See Explorer.explore_type for more information.
|
| + """
|
| + actual_type = datatype.strip_typedefs()
|
| + if is_child:
|
| + print ("The type of %s is a typedef of type '%s'." %
|
| + (name, str(actual_type)))
|
| + else:
|
| + print ("The type '%s' is a typedef of type '%s'." %
|
| + (name, str(actual_type)))
|
| +
|
| + Explorer.explore_type(name, actual_type, is_child)
|
| + return False
|
| +
|
| +
|
| +class ExploreUtils(object):
|
| + """Internal class which provides utilities for the main command classes."""
|
| +
|
| + @staticmethod
|
| + def check_args(name, arg_str):
|
| + """Utility to check if adequate number of arguments are passed to an
|
| + explore command.
|
| +
|
| + Arguments:
|
| + name: The name of the explore command.
|
| + arg_str: The argument string passed to the explore command.
|
| +
|
| + Returns:
|
| + True if adequate arguments are passed, false otherwise.
|
| +
|
| + Raises:
|
| + gdb.GdbError if adequate arguments are not passed.
|
| + """
|
| + if len(arg_str) < 1:
|
| + raise gdb.GdbError("ERROR: '%s' requires an argument."
|
| + % name)
|
| + return False
|
| + else:
|
| + return True
|
| +
|
| + @staticmethod
|
| + def get_type_from_str(type_str):
|
| + """A utility function to deduce the gdb.Type value from a string
|
| + representing the type.
|
| +
|
| + Arguments:
|
| + type_str: The type string from which the gdb.Type value should be
|
| + deduced.
|
| +
|
| + Returns:
|
| + The deduced gdb.Type value if possible, None otherwise.
|
| + """
|
| + try:
|
| + # Assume the current language to be C/C++ and make a try.
|
| + return gdb.parse_and_eval("(%s *)0" % type_str).type.target()
|
| + except RuntimeError:
|
| + # If assumption of current language to be C/C++ was wrong, then
|
| + # lookup the type using the API.
|
| + try:
|
| + return gdb.lookup_type(type_str)
|
| + except RuntimeError:
|
| + return None
|
| +
|
| + @staticmethod
|
| + def get_value_from_str(value_str):
|
| + """A utility function to deduce the gdb.Value value from a string
|
| + representing the value.
|
| +
|
| + Arguments:
|
| + value_str: The value string from which the gdb.Value value should
|
| + be deduced.
|
| +
|
| + Returns:
|
| + The deduced gdb.Value value if possible, None otherwise.
|
| + """
|
| + try:
|
| + return gdb.parse_and_eval(value_str)
|
| + except RuntimeError:
|
| + return None
|
| +
|
| +
|
| +class ExploreCommand(gdb.Command):
|
| + """Explore a value or a type valid in the current context.
|
| +
|
| + Usage:
|
| +
|
| + explore ARG
|
| +
|
| + - ARG is either a valid expression or a type name.
|
| + - At any stage of exploration, hit the return key (instead of a
|
| + choice, if any) to return to the enclosing type or value.
|
| + """
|
| +
|
| + def __init__(self):
|
| + super(ExploreCommand, self).__init__(name = "explore",
|
| + command_class = gdb.COMMAND_DATA,
|
| + prefix = True)
|
| +
|
| + def invoke(self, arg_str, from_tty):
|
| + if ExploreUtils.check_args("explore", arg_str) == False:
|
| + return
|
| +
|
| + # Check if it is a value
|
| + value = ExploreUtils.get_value_from_str(arg_str)
|
| + if value is not None:
|
| + Explorer.explore_expr(arg_str, value, False)
|
| + return
|
| +
|
| + # If it is not a value, check if it is a type
|
| + datatype = ExploreUtils.get_type_from_str(arg_str)
|
| + if datatype is not None:
|
| + Explorer.explore_type(arg_str, datatype, False)
|
| + return
|
| +
|
| + # If it is neither a value nor a type, raise an error.
|
| + raise gdb.GdbError(
|
| + ("'%s' neither evaluates to a value nor is a type "
|
| + "in the current context." %
|
| + arg_str))
|
| +
|
| +
|
| +class ExploreValueCommand(gdb.Command):
|
| + """Explore value of an expression valid in the current context.
|
| +
|
| + Usage:
|
| +
|
| + explore value ARG
|
| +
|
| + - ARG is a valid expression.
|
| + - At any stage of exploration, hit the return key (instead of a
|
| + choice, if any) to return to the enclosing value.
|
| + """
|
| +
|
| + def __init__(self):
|
| + super(ExploreValueCommand, self).__init__(
|
| + name = "explore value", command_class = gdb.COMMAND_DATA)
|
| +
|
| + def invoke(self, arg_str, from_tty):
|
| + if ExploreUtils.check_args("explore value", arg_str) == False:
|
| + return
|
| +
|
| + value = ExploreUtils.get_value_from_str(arg_str)
|
| + if value is None:
|
| + raise gdb.GdbError(
|
| + (" '%s' does not evaluate to a value in the current "
|
| + "context." %
|
| + arg_str))
|
| + return
|
| +
|
| + Explorer.explore_expr(arg_str, value, False)
|
| +
|
| +
|
| +class ExploreTypeCommand(gdb.Command):
|
| + """Explore a type or the type of an expression valid in the current
|
| + context.
|
| +
|
| + Usage:
|
| +
|
| + explore type ARG
|
| +
|
| + - ARG is a valid expression or a type name.
|
| + - At any stage of exploration, hit the return key (instead of a
|
| + choice, if any) to return to the enclosing type.
|
| + """
|
| +
|
| + def __init__(self):
|
| + super(ExploreTypeCommand, self).__init__(
|
| + name = "explore type", command_class = gdb.COMMAND_DATA)
|
| +
|
| + def invoke(self, arg_str, from_tty):
|
| + if ExploreUtils.check_args("explore type", arg_str) == False:
|
| + return
|
| +
|
| + datatype = ExploreUtils.get_type_from_str(arg_str)
|
| + if datatype is not None:
|
| + Explorer.explore_type(arg_str, datatype, False)
|
| + return
|
| +
|
| + value = ExploreUtils.get_value_from_str(arg_str)
|
| + if value is not None:
|
| + print "'%s' is of type '%s'." % (arg_str, str(value.type))
|
| + Explorer.explore_type(str(value.type), value.type, False)
|
| +
|
| + raise gdb.GdbError(("'%s' is not a type or value in the current "
|
| + "context." % arg_str))
|
| +
|
| +
|
| +Explorer.init_env()
|
| +
|
| +ExploreCommand()
|
| +ExploreValueCommand()
|
| +ExploreTypeCommand()
|
|
|