]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/lib/gdb/unwinder.py
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / unwinder.py
CommitLineData
1d506c26 1# Copyright (C) 2015-2024 Free Software Foundation, Inc.
d11916aa
SS
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16"""Unwinder class and register_unwinder function."""
17
18import gdb
19
20
21class Unwinder(object):
22 """Base class (or a template) for frame unwinders written in Python.
23
24 An unwinder has a single method __call__ and the attributes
25 described below.
26
27 Attributes:
28 name: The name of the unwinder.
29 enabled: A boolean indicating whether the unwinder is enabled.
30 """
31
32 def __init__(self, name):
33 """Constructor.
34
35 Args:
36 name: An identifying name for the unwinder.
37 """
6bf5f25b
AB
38
39 if not isinstance(name, str):
40 raise TypeError("incorrect type for name: %s" % type(name))
41
42 self._name = name
43 self._enabled = True
44
45 @property
46 def name(self):
47 return self._name
48
49 @property
50 def enabled(self):
51 return self._enabled
52
53 @enabled.setter
54 def enabled(self, value):
55 if not isinstance(value, bool):
56 raise TypeError("incorrect type for enabled attribute: %s" % type(value))
57 self._enabled = value
58 gdb.invalidate_cached_frames()
d11916aa
SS
59
60 def __call__(self, pending_frame):
61 """GDB calls this method to unwind a frame.
62
63 Arguments:
64 pending_frame: gdb.PendingFrame instance.
65
66 Returns:
67 gdb.UnwindInfo instance.
68 """
69 raise NotImplementedError("Unwinder __call__.")
70
71
3712e78c
AB
72class FrameId(object):
73 """A Frame-ID class for use when creating gdb.UnwindInfo objects.
74
75 Attributes (all read-only):
76 pc: Program counter value.
77 sp: The stack-pointer value.
78 special: An alternative stack-pointer value, can be None."""
79
80 def __init__(self, sp, pc, special=None):
81 self._sp = sp
82 self._pc = pc
83 self._special = special
84
85 @property
86 def sp(self):
87 return self._sp
88
89 @property
90 def pc(self):
91 return self._pc
92
93 @property
94 def special(self):
95 return self._special
96
97
d11916aa
SS
98def register_unwinder(locus, unwinder, replace=False):
99 """Register unwinder in given locus.
100
101 The unwinder is prepended to the locus's unwinders list. Unwinder
102 name should be unique.
103
104 Arguments:
105 locus: Either an objfile, progspace, or None (in which case
106 the unwinder is registered globally).
107 unwinder: An object of a gdb.Unwinder subclass
108 replace: If True, replaces existing unwinder with the same name.
109 Otherwise, raises exception if unwinder with the same
110 name already exists.
111
112 Returns:
113 Nothing.
114
115 Raises:
116 RuntimeError: Unwinder name is not unique
117 TypeError: Bad locus type
118 """
119 if locus is None:
120 if gdb.parameter("verbose"):
121 gdb.write("Registering global %s unwinder ...\n" % unwinder.name)
122 locus = gdb
123 elif isinstance(locus, gdb.Objfile) or isinstance(locus, gdb.Progspace):
124 if gdb.parameter("verbose"):
13123da8
SM
125 gdb.write(
126 "Registering %s unwinder for %s ...\n" % (unwinder.name, locus.filename)
127 )
d11916aa
SS
128 else:
129 raise TypeError("locus should be gdb.Objfile or gdb.Progspace or None")
130
131 i = 0
132 for needle in locus.frame_unwinders:
133 if needle.name == unwinder.name:
134 if replace:
135 del locus.frame_unwinders[i]
136 else:
13123da8 137 raise RuntimeError("Unwinder %s already exists." % unwinder.name)
d11916aa
SS
138 i += 1
139 locus.frame_unwinders.insert(0, unwinder)
e0f3fd7c 140 gdb.invalidate_cached_frames()