summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python/py-framefilter.py
blob: 900af4a32d6ff982cb8e3192f57d966f3fafe31d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# Copyright (C) 2013-2020 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/>.

# This file is part of the GDB testsuite.  It tests Python-based
# frame-filters.
import gdb
import itertools
from gdb.FrameDecorator import FrameDecorator
import copy

class Reverse_Function (FrameDecorator):

    def __init__(self, fobj):
        super(Reverse_Function, self).__init__(fobj)
        self.fobj = fobj

    def function (self):
        fname = str (self.fobj.function())
        if (fname == None or fname == ""):
            return None
        if fname == 'end_func':
            extra = self.fobj.inferior_frame().read_var('str').string()
        else:
            extra = ''
        fname = fname[::-1] + extra
        return fname

class Dummy (FrameDecorator):

    def __init__(self, fobj):
        super(Dummy, self).__init__(fobj)
        self.fobj = fobj

    def function (self):
        return "Dummy function"

    def address (self):
        return 0x123

    def filename (self):
        return "Dummy filename"

    def frame_args (self):
        return [("Foo",gdb.Value(12)),("Bar","Stuff"), ("FooBar",42)]

    def frame_locals (self):
        return []

    def line (self):
        return 0

    def elided (self):
        return None

class FrameFilter ():

    def __init__ (self):
        self.name = "Reverse"
        self.priority = 100
        self.enabled = True
        gdb.frame_filters [self.name] = self

    def filter (self, frame_iter):
        # Python 3.x moved the itertools.imap functionality to map(),
        # so check if it is available.
        if hasattr(itertools, "imap"):
            frame_iter = itertools.imap (Reverse_Function,
                                         frame_iter)
        else:
            frame_iter = map(Reverse_Function, frame_iter)

        return frame_iter

class ElidingFrameDecorator(FrameDecorator):

    def __init__(self, frame, elided_frames):
        super(ElidingFrameDecorator, self).__init__(frame)
        self.elided_frames = elided_frames

    def elided(self):
        return iter(self.elided_frames)

    def address (self):
        # Regression test for an overflow in the python layer.
        bitsize = 8 * gdb.lookup_type('void').pointer().sizeof
        mask = (1 << bitsize) - 1
        return 0xffffffffffffffff & mask

class ElidingIterator:
    def __init__(self, ii):
        self.input_iterator = ii

    def __iter__(self):
        return self

    def next(self):
        frame = next(self.input_iterator)
        if str(frame.function()) != 'func1':
            return frame

        # Suppose we want to return the 'func1' frame but elide the
        # next frame.  E.g., if call in our interpreter language takes
        # two C frames to implement, and the first one we see is the
        # "sentinel".
        elided = next(self.input_iterator)
        return ElidingFrameDecorator(frame, [elided])

    # Python 3.x requires __next__(self) while Python 2.x requires
    # next(self).  Define next(self), and for Python 3.x create this
    # wrapper.
    def __next__(self):
        return self.next()

class FrameElider ():

    def __init__ (self):
        self.name = "Elider"
        self.priority = 900
        self.enabled = True
        gdb.frame_filters [self.name] = self

    def filter (self, frame_iter):
        return ElidingIterator (frame_iter)

# This is here so the test can change the kind of error that is
# thrown.
name_error = RuntimeError

# A simple decorator that gives an error when computing the function.
class ErrorInName(FrameDecorator):
    def __init__(self, frame):
        FrameDecorator.__init__(self, frame)

    def function(self):
        raise name_error('whoops')

# A filter that supplies buggy frames.  Disabled by default.
class ErrorFilter():
    def __init__ (self):
        self.name = "Error"
        self.priority = 1
        self.enabled = False
        gdb.frame_filters [self.name] = self

    def filter(self, frame_iter):
        # Python 3.x moved the itertools.imap functionality to map(),
        # so check if it is available.
        if hasattr(itertools, "imap"):
            return itertools.imap (ErrorInName, frame_iter)
        else:
            return map(ErrorInName, frame_iter)

FrameFilter()
FrameElider()
ErrorFilter()