1 # Copyright (C) 2021-2023 Free Software Foundation, Inc.
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.
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.
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/>.
17 from gdb
.unwinder
import Unwinder
19 # Set this to the stack level the backtrace should be corrupted at.
20 # This will only work for frame 1, 3, or 5 in the test this unwinder
24 # Set this to the stack frame size of frames 1, 3, and 5. These
25 # frames will all have the same stack frame size as they are the same
26 # function called recursively.
30 class FrameId(object):
31 def __init__(self
, sp
, pc
):
44 class TestUnwinder(Unwinder
):
46 Unwinder
.__init
__(self
, "stop at level")
48 def __call__(self
, pending_frame
):
52 if stop_at_level
is None or pending_frame
.level() != stop_at_level
:
55 if stack_adjust
is None:
56 raise gdb
.GdbError("invalid stack_adjust")
58 if not stop_at_level
in [1, 3, 5]:
59 raise gdb
.GdbError("invalid stop_at_level")
61 sp_desc
= pending_frame
.architecture().registers().find("sp")
62 sp
= pending_frame
.read_register(sp_desc
) + stack_adjust
63 pc
= (gdb
.lookup_symbol("normal_func"))[0].value().address
64 unwinder
= pending_frame
.create_unwind_info(FrameId(sp
, pc
))
66 for reg
in pending_frame
.architecture().registers("general"):
67 val
= pending_frame
.read_register(reg
)
68 unwinder
.add_saved_register(reg
, val
)
72 gdb
.unwinder
.register_unwinder(None, TestUnwinder(), True)
74 # When loaded, it is expected that the stack looks like:
76 # main -> normal_func -> inline_func -> normal_func -> inline_func -> normal_func -> inline_func
78 # Compute the stack frame size of normal_func, which has inline_func
80 f0
= gdb
.newest_frame()
83 f0_sp
= f0
.read_register("sp")
84 f2_sp
= f2
.read_register("sp")
85 stack_adjust
= f2_sp
- f0_sp