]> Git Repo - binutils.git/blob - gdb/python/lib/gdb/command/unwinders.py
59ee67cc7b356b0b3a325a86da450e00fc3562cc
[binutils.git] / gdb / python / lib / gdb / command / unwinders.py
1 # Unwinder commands.
2 # Copyright 2015-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 import gdb
18 import re
19
20
21 def validate_regexp(exp, idstring):
22     try:
23         return re.compile(exp)
24     except SyntaxError:
25         raise SyntaxError("Invalid %s regexp: %s." % (idstring, exp))
26
27
28 def parse_unwinder_command_args(arg):
29     """Internal utility to parse unwinder command argv.
30
31     Arguments:
32         arg: The arguments to the command. The format is:
33              [locus-regexp [name-regexp]]
34
35     Returns:
36         A 2-tuple of compiled regular expressions.
37
38     Raises:
39         SyntaxError: an error processing ARG
40     """
41
42     argv = gdb.string_to_argv(arg)
43     argc = len(argv)
44     if argc > 2:
45         raise SyntaxError("Too many arguments.")
46     locus_regexp = ""
47     name_regexp = ""
48     if argc >= 1:
49         locus_regexp = argv[0]
50         if argc >= 2:
51             name_regexp = argv[1]
52     return (
53         validate_regexp(locus_regexp, "locus"),
54         validate_regexp(name_regexp, "unwinder"),
55     )
56
57
58 class InfoUnwinder(gdb.Command):
59     """GDB command to list unwinders.
60
61     Usage: info unwinder [LOCUS-REGEXP [NAME-REGEXP]]
62
63     LOCUS-REGEXP is a regular expression matching the location of the
64     unwinder.  If it is omitted, all registered unwinders from all
65     loci are listed.  A locus can be 'global', 'progspace' to list
66     the unwinders from the current progspace, or a regular expression
67     matching filenames of objfiles.
68
69     NAME-REGEXP is a regular expression to filter unwinder names.  If
70     this omitted for a specified locus, then all registered unwinders
71     in the locus are listed."""
72
73     def __init__(self):
74         super(InfoUnwinder, self).__init__("info unwinder", gdb.COMMAND_STACK)
75
76     def list_unwinders(self, title, unwinders, name_re):
77         """Lists the unwinders whose name matches regexp.
78
79         Arguments:
80             title: The line to print before the list.
81             unwinders: The list of the unwinders.
82             name_re: unwinder name filter.
83         """
84         if not unwinders:
85             return
86         print(title)
87         for unwinder in unwinders:
88             if name_re.match(unwinder.name):
89                 print(
90                     "  %s%s"
91                     % (unwinder.name, "" if unwinder.enabled else " [disabled]")
92                 )
93
94     def invoke(self, arg, from_tty):
95         locus_re, name_re = parse_unwinder_command_args(arg)
96         if locus_re.match("global"):
97             self.list_unwinders("Global:", gdb.frame_unwinders, name_re)
98         if locus_re.match("progspace"):
99             cp = gdb.current_progspace()
100             self.list_unwinders(
101                 "Progspace %s:" % cp.filename, cp.frame_unwinders, name_re
102             )
103         for objfile in gdb.objfiles():
104             if locus_re.match(objfile.filename):
105                 self.list_unwinders(
106                     "Objfile %s:" % objfile.filename, objfile.frame_unwinders, name_re
107                 )
108
109
110 def do_enable_unwinder1(unwinders, name_re, flag):
111     """Enable/disable unwinders whose names match given regex.
112
113     Arguments:
114         unwinders: The list of unwinders.
115         name_re: Unwinder name filter.
116         flag: Enable/disable.
117
118     Returns:
119         The number of unwinders affected.
120     """
121     total = 0
122     for unwinder in unwinders:
123         if name_re.match(unwinder.name):
124             unwinder.enabled = flag
125             total += 1
126     return total
127
128
129 def do_enable_unwinder(arg, flag):
130     """Enable/disable unwinder(s)."""
131     (locus_re, name_re) = parse_unwinder_command_args(arg)
132     total = 0
133     if locus_re.match("global"):
134         total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag)
135     if locus_re.match("progspace"):
136         total += do_enable_unwinder1(
137             gdb.current_progspace().frame_unwinders, name_re, flag
138         )
139     for objfile in gdb.objfiles():
140         if locus_re.match(objfile.filename):
141             total += do_enable_unwinder1(objfile.frame_unwinders, name_re, flag)
142     if total > 0:
143         gdb.invalidate_cached_frames()
144     print(
145         "%d unwinder%s %s"
146         % (total, "" if total == 1 else "s", "enabled" if flag else "disabled")
147     )
148
149
150 class EnableUnwinder(gdb.Command):
151     """GDB command to enable unwinders.
152
153     Usage: enable unwinder [LOCUS-REGEXP [NAME-REGEXP]]
154
155     LOCUS-REGEXP is a regular expression specifying the unwinders to
156     enable.  It can 'global', 'progspace', or the name of an objfile
157     within that progspace.
158
159     NAME_REGEXP is a regular expression to filter unwinder names.  If
160     this omitted for a specified locus, then all registered unwinders
161     in the locus are affected."""
162
163     def __init__(self):
164         super(EnableUnwinder, self).__init__("enable unwinder", gdb.COMMAND_STACK)
165
166     def invoke(self, arg, from_tty):
167         """GDB calls this to perform the command."""
168         do_enable_unwinder(arg, True)
169
170
171 class DisableUnwinder(gdb.Command):
172     """GDB command to disable the specified unwinder.
173
174     Usage: disable unwinder [LOCUS-REGEXP [NAME-REGEXP]]
175
176     LOCUS-REGEXP is a regular expression specifying the unwinders to
177     disable.  It can 'global', 'progspace', or the name of an objfile
178     within that progspace.
179
180     NAME_REGEXP is a regular expression to filter unwinder names.  If
181     this omitted for a specified locus, then all registered unwinders
182     in the locus are affected."""
183
184     def __init__(self):
185         super(DisableUnwinder, self).__init__("disable unwinder", gdb.COMMAND_STACK)
186
187     def invoke(self, arg, from_tty):
188         """GDB calls this to perform the command."""
189         do_enable_unwinder(arg, False)
190
191
192 def register_unwinder_commands():
193     """Installs the unwinder commands."""
194     InfoUnwinder()
195     EnableUnwinder()
196     DisableUnwinder()
197
198
199 register_unwinder_commands()
This page took 0.026 seconds and 2 git commands to generate.