# Copyright (C) 2026 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/>.

# A class which is a GDB frame unwinder.  This frame unwinder can be
# used to corrupt the backtrace by tricking GDB into believing that
# there is a repeated frame-id in the backtrace.
#
# Sourcing this script creates a global called 'global_unwinder' and
# registers a global unwinder called 'stop-at-level'.  The unwinder
# needs to be primed with the frame-ids copied from the current stack,
# this can be done by enabling the unwinder using the GDB command:
#
# (gdb) enable unwinder global stop-at-level
#
# You then need to set the level at which to corrupt the stack, e.g.:
#
# (gdb) python global_unwinder.stop_at_level = 3
#
# This will allow the frames #0, #1, #2, and #3 to print correctly,
# but frame #4 will appear to be a repeat of frame #3, so GDB will
# terminate the backtrace.
#
# As the unwinder relies on cached frame-ids, then resuming the
# inferior for which the frame-ids were cached will cause the unwinder
# to auto-disable itself, after which you'll need to re-enable the
# next time the inferior stops.
#
# Changing the 'global_unwinder.stop_at_level' will flush the frame
# cache, so you can test breaking the stack at different levels.


import re

import gdb
from gdb.unwinder import FrameId, Unwinder


class corrupt_stack_unwinder(Unwinder):
    def __init__(self):
        # Is this unwinder enabled or not?  Accessed via the 'enabled'
        # property.
        self._enabled = True

        # List of FrameId instances, one for each stack frame.  This list is
        # populated when this file is sourced into GDB.
        self._frame_ids = []

        # The inferior for which we cached self._frame_ids.  The
        # unwinder will only work within this inferior.
        self._inferior = None

        # At what stack level should we break the unwind?
        self._stop_at_level = None

        Unwinder.__init__(self, "stop-at-level")

        if gdb.selected_inferior().pid > 0:
            self._update_frame_id_cache()
        else:
            self._enabled = False

        gdb.events.cont.connect(lambda ev: self._continued_event_handler(ev))

    # Assume that the current inferior has a stack.  Collect a FrameId
    # object for each level of the current stack.
    def _update_frame_id_cache(self):
        self._frame_ids = []
        self._inferior = gdb.selected_inferior()

        frame = gdb.newest_frame()
        while frame is not None:
            # Get the frame-id in a verbose text form.
            output = gdb.execute(
                "maint print frame-id %d" % frame.level(), to_string=True
            )

            # Parse the frame-id in OUTPUT, find the stack and code addresses.
            match = re.search(r"stack=(0x[0-9a-fA-F]+).*?code=(0x[0-9a-fA-F]+)", output)
            if not match:
                raise gdb.GdbError(
                    "Could not parse frame-id for frame #%d" % frame.level()
                )

            # Create the FrameId object.
            sp_addr = int(match.group(1), 16)
            pc_addr = int(match.group(2), 16)
            self._frame_ids.append(FrameId(sp_addr, pc_addr))

            frame = frame.older()

    # Called when an inferior continues.  If this is the inferior for
    # which this unwinder collected the stack, then discard the
    # collected FrameId objects and disable the unwinder.
    def _continued_event_handler(self, event):
        if gdb.selected_inferior() == self._inferior:
            self._enabled = False
            self._frame_ids = []
            self._inferior = None

    # To aid debugging, print the captured FrameId instances.
    def print_frame_ids(self):
        for level, fid in enumerate(self._frame_ids):
            print(
                "frame-id for frame #%s: {stack=0x%x,code=0x%x}"
                % (level, fid.sp, fid.pc)
            )

    def __call__(self, pending_frame):
        if self.stop_at_level is None or pending_frame.level() != self.stop_at_level:
            return None

        if gdb.selected_inferior() != self._inferior:
            return None

        if len(self._frame_ids) <= self.stop_at_level:
            raise gdb.GdbError("not enough parsed frame-ids")

        # Set the frame-id for this frame to its actual, expected
        # frame-id, which we captured in the FRAME_IDS list.
        unwinder = pending_frame.create_unwind_info(self._frame_ids[self.stop_at_level])

        # Provide the register values for the caller frame, that is,
        # the frame at 'STOP_AT_LEVEL + 1'.
        #
        # We forward all of the register values unchanged from this
        # frame.
        #
        # What this means is that, as far as GDB is concerned, the
        # caller frame will appear to be identical to this frame.  Of
        # particular importance, we send $pc and $sp unchanged to the
        # caller frame.
        #
        # Because the caller frame has the same $pc and $sp as this
        # frame, GDB will compute the same frame-id for the caller
        # frame as we just supplied for this frame (above).  This
        # creates the artificial frame cycle which is the whole point
        # of this test.
        #
        # NOTE: Forwarding all registers unchanged like this to the
        # caller frame is not how you'd normally write a frame
        # unwinder.  Some registers might indeed be unmodified between
        # frames, but we'd usually expect the $sp and/or the $pc to
        # change.  This test is deliberately doing something weird in
        # order to force a cycle, and so test GDB.
        for reg in pending_frame.architecture().registers("general"):
            val = pending_frame.read_register(reg)
            # Having unavailable registers leads to a fall back to the standard
            # unwinders.  Don't add unavailable registers to avoid this.
            if str(val) == "<unavailable>":
                continue
            unwinder.add_saved_register(reg, val)
        return unwinder

    @property
    def enabled(self):
        return self._enabled

    @enabled.setter
    def enabled(self, val):
        if val:
            self._enabled = False
            self._update_frame_id_cache()

        self._enabled = val

    @property
    def stop_at_level(self):
        return self._stop_at_level

    @stop_at_level.setter
    def stop_at_level(self, val):
        self._stop_at_level = val
        gdb.invalidate_cached_frames()


global_unwinder = corrupt_stack_unwinder()
gdb.unwinder.register_unwinder(None, global_unwinder, True)
