1# Copyright (C) 2021-2023 Free Software Foundation, Inc. 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 16import gdb 17from gdb.unwinder import Unwinder 18 19 20class FrameId(object): 21 def __init__(self, sp, pc): 22 self._sp = sp 23 self._pc = pc 24 25 @property 26 def sp(self): 27 return self._sp 28 29 @property 30 def pc(self): 31 return self._pc 32 33 34class TestUnwinder(Unwinder): 35 def __init__(self, use_descriptors): 36 if use_descriptors: 37 tag = "using descriptors" 38 else: 39 tag = "using strings" 40 41 Unwinder.__init__(self, "break unwinding %s" % tag) 42 self._use_descriptors = use_descriptors 43 44 def __call__(self, pending_frame): 45 pc_desc = pending_frame.architecture().registers().find("pc") 46 pc = pending_frame.read_register(pc_desc) 47 48 sp_desc = pending_frame.architecture().registers().find("sp") 49 sp = pending_frame.read_register(sp_desc) 50 51 block = gdb.block_for_pc(int(pc)) 52 if block is None: 53 return None 54 func = block.function 55 if func is None: 56 return None 57 if str(func) != "bar": 58 return None 59 60 fid = FrameId(pc, sp) 61 unwinder = pending_frame.create_unwind_info(fid) 62 if self._use_descriptors: 63 unwinder.add_saved_register(pc_desc, pc) 64 unwinder.add_saved_register(sp_desc, sp) 65 else: 66 unwinder.add_saved_register("pc", pc) 67 unwinder.add_saved_register("sp", sp) 68 return unwinder 69 70 71gdb.unwinder.register_unwinder(None, TestUnwinder(True), True) 72gdb.unwinder.register_unwinder(None, TestUnwinder(False), True) 73