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