Home | History | Annotate | Download | only in command
      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