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

import struct
import sys

import gdb
import gdb.disassembler
from gdb.disassembler import Disassembler, DisassemblerResult

# A global, holds the program-counter address at which we should
# perform the extra disassembly that this script provides.
current_pc = None


def builtin_disassemble_wrapper(info):
    result = gdb.disassembler.builtin_disassemble(info)
    assert result.length > 0
    assert len(result.parts) > 0
    tmp_str = ""
    for p in result.parts:
        assert p.string == str(p)
        tmp_str += p.string
    assert tmp_str == result.string
    return result


def check_building_disassemble_result():
    """Check that we can create DisassembleResult objects correctly."""

    result = gdb.disassembler.DisassemblerResult()

    print("PASS")


def is_nop(s):
    return s == "nop" or s == "nop\t0" or s == "nop\t{0}"


# Remove all currently registered disassemblers.
def remove_all_python_disassemblers():
    for a in gdb.architecture_names():
        gdb.disassembler.register_disassembler(None, a)
    gdb.disassembler.register_disassembler(None, None)


class TestDisassembler(Disassembler):
    """A base class for disassemblers within this script to inherit from.
    Implements the __call__ method and ensures we only do any
    disassembly wrapping for the global CURRENT_PC."""

    def __init__(self):
        global current_pc

        super().__init__("TestDisassembler")
        self.__info = None
        if current_pc == None:
            raise gdb.GdbError("no current_pc set")

    def __call__(self, info):
        global current_pc

        if info.address != current_pc:
            return None
        self.__info = info
        return self.disassemble(info)

    def get_info(self):
        return self.__info

    def disassemble(self, info):
        raise NotImplementedError("override the disassemble method")


class ShowInfoRepr(TestDisassembler):
    """Call the __repr__ method on the DisassembleInfo, convert the result
    to a string, and incude it in a comment in the disassembler output."""

    def disassemble(self, info):
        comment = "\t## " + repr(info)
        result = builtin_disassemble_wrapper(info)
        string = result.string + comment
        length = result.length
        return DisassemblerResult(length=length, string=string)


class ShowInfoSubClassRepr(TestDisassembler):
    """Create a sub-class of DisassembleInfo.  Create an instace of this
    sub-class and call the __repr__ method on it.  Convert the result
    to a string, and incude it in a comment in the disassembler
    output.  The DisassembleInfo sub-class does not override __repr__
    so we are calling the implementation on the parent class."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        """A wrapper around DisassembleInfo, doesn't add any new
        functionality, just gives a new name in order to check the
        __repr__ functionality."""

        def __init__(self, info):
            super().__init__(info)

    def disassemble(self, info):
        info = self.MyInfo(info)
        comment = "\t## " + repr(info)
        result = builtin_disassemble_wrapper(info)
        string = result.string + comment
        length = result.length
        return DisassemblerResult(length=length, string=string)


class ShowResultRepr(TestDisassembler):
    """Call the __repr__ method on the DisassemblerResult, convert the
    result to a string, and incude it in a comment in the disassembler
    output."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        comment = "\t## " + repr(result)
        string = result.string + comment
        length = result.length
        return DisassemblerResult(length=length, string=string)


class ShowResultStr(TestDisassembler):
    """Call the __str__ method on a DisassemblerResult object, incude the
    resulting string in a comment within the disassembler output."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        comment = "\t## " + str(result)
        string = result.string + comment
        length = result.length
        return DisassemblerResult(length=length, string=string, parts=None)


class GlobalPreInfoDisassembler(TestDisassembler):
    """Check the attributes of DisassembleInfo before disassembly has occurred."""

    def disassemble(self, info):
        ad = info.address
        ar = info.architecture

        if ad != current_pc:
            raise gdb.GdbError("invalid address")

        if not isinstance(ar, gdb.Architecture):
            raise gdb.GdbError("invalid architecture type")

        result = builtin_disassemble_wrapper(info)

        text = result.string + "\t## ad = 0x%x, ar = %s" % (ad, ar.name())
        return DisassemblerResult(result.length, text)


class GlobalPostInfoDisassembler(TestDisassembler):
    """Check the attributes of DisassembleInfo after disassembly has occurred."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)

        ad = info.address
        ar = info.architecture

        if ad != current_pc:
            raise gdb.GdbError("invalid address")

        if not isinstance(ar, gdb.Architecture):
            raise gdb.GdbError("invalid architecture type")

        text = result.string + "\t## ad = 0x%x, ar = %s" % (ad, ar.name())
        return DisassemblerResult(result.length, text)


class GlobalReadDisassembler(TestDisassembler):
    """Check the DisassembleInfo.read_memory method.  Calls the builtin
    disassembler, then reads all of the bytes of this instruction, and
    adds them as a comment to the disassembler output."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        len = result.length
        str = ""
        for o in range(len):
            if str != "":
                str += " "
            v = bytes(info.read_memory(1, o))[0]
            if sys.version_info[0] < 3:
                v = struct.unpack("<B", v)
            str += "0x%02x" % v
        text = result.string + "\t## bytes = %s" % str
        return DisassemblerResult(result.length, text)


class GlobalAddrDisassembler(TestDisassembler):
    """Check the gdb.format_address method."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        arch = info.architecture
        addr = info.address
        program_space = info.progspace
        str = gdb.format_address(addr, program_space, arch)
        text = result.string + "\t## addr = %s" % str
        return DisassemblerResult(result.length, text)


class GdbErrorEarlyDisassembler(TestDisassembler):
    """Raise a GdbError instead of performing any disassembly."""

    def disassemble(self, info):
        raise gdb.GdbError("GdbError instead of a result")


class RuntimeErrorEarlyDisassembler(TestDisassembler):
    """Raise a RuntimeError instead of performing any disassembly."""

    def disassemble(self, info):
        raise RuntimeError("RuntimeError instead of a result")


class GdbErrorLateDisassembler(TestDisassembler):
    """Raise a GdbError after calling the builtin disassembler."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        raise gdb.GdbError("GdbError after builtin disassembler")


class RuntimeErrorLateDisassembler(TestDisassembler):
    """Raise a RuntimeError after calling the builtin disassembler."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        raise RuntimeError("RuntimeError after builtin disassembler")


class MemoryErrorEarlyDisassembler(TestDisassembler):
    """Throw a memory error, ignore the error and disassemble."""

    def disassemble(self, info):
        tag = "## FAIL"
        try:
            info.read_memory(1, -info.address - 1)
        except gdb.MemoryError:
            tag = "## AFTER ERROR"
        result = builtin_disassemble_wrapper(info)
        text = result.string + "\t" + tag
        return DisassemblerResult(result.length, text)


class MemoryErrorLateDisassembler(TestDisassembler):
    """Throw a memory error after calling the builtin disassembler, but
    before we return a result."""

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        # The following read will throw an error.
        info.read_memory(1, -info.address - 1)
        return DisassemblerResult(1, "BAD")


class RethrowMemoryErrorDisassembler(TestDisassembler):
    """Catch and rethrow a memory error."""

    def disassemble(self, info):
        try:
            info.read_memory(1, -info.address - 1)
        except gdb.MemoryError as e:
            raise gdb.MemoryError("cannot read code at address -1")
        return DisassemblerResult(1, "BAD")


class ResultOfWrongType(TestDisassembler):
    """Return something that is not a DisassemblerResult from disassemble method"""

    class Blah:
        def __init__(self, length, string):
            self.length = length
            self.string = string

    def disassemble(self, info):
        return self.Blah(1, "ABC")


class ResultOfVeryWrongType(TestDisassembler):
    """Return something that is not a DisassemblerResult from disassemble
    method.  The thing returned will raise an exception if used in an
    isinstance() call, or in PyObject_IsInstance from C++.
    """

    class Blah:
        def __init__(self):
            pass

        @property
        def __class__(self):
            raise RuntimeError("error from __class__ in Blah")

    def disassemble(self, info):
        return self.Blah()


class TaggingDisassembler(TestDisassembler):
    """A simple disassembler that just tags the output."""

    def __init__(self, tag):
        super().__init__()
        self._tag = tag

    def disassemble(self, info):
        result = builtin_disassemble_wrapper(info)
        text = result.string + "\t## tag = %s" % self._tag
        return DisassemblerResult(result.length, text)


class GlobalCachingDisassembler(TestDisassembler):
    """A disassembler that caches the DisassembleInfo that is passed in,
    as well as a copy of the original DisassembleInfo.

    Once the call into the disassembler is complete then the
    DisassembleInfo objects become invalid, and any calls into them
    should trigger an exception."""

    # This is where we cache the DisassembleInfo objects.
    cached_insn_disas = []

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

    def disassemble(self, info):
        """Disassemble the instruction, add a CACHED comment to the output,
        and cache the DisassembleInfo so that it is not garbage collected."""
        GlobalCachingDisassembler.cached_insn_disas.append(info)
        GlobalCachingDisassembler.cached_insn_disas.append(self.MyInfo(info))
        result = builtin_disassemble_wrapper(info)
        text = result.string + "\t## CACHED"
        return DisassemblerResult(result.length, text)

    @staticmethod
    def check():
        """Check that all of the methods on the cached DisassembleInfo trigger an
        exception."""
        for info in GlobalCachingDisassembler.cached_insn_disas:
            assert isinstance(info, gdb.disassembler.DisassembleInfo)
            assert not info.is_valid()
            try:
                val = info.address
                raise gdb.GdbError("DisassembleInfo.address is still valid")
            except RuntimeError as e:
                assert str(e) == "DisassembleInfo is no longer valid."
            except:
                raise gdb.GdbError(
                    "DisassembleInfo.address raised an unexpected exception"
                )

            try:
                val = info.architecture
                raise gdb.GdbError("DisassembleInfo.architecture is still valid")
            except RuntimeError as e:
                assert str(e) == "DisassembleInfo is no longer valid."
            except:
                raise gdb.GdbError(
                    "DisassembleInfo.architecture raised an unexpected exception"
                )

            try:
                val = info.read_memory(1, 0)
                raise gdb.GdbError("DisassembleInfo.read is still valid")
            except RuntimeError as e:
                assert str(e) == "DisassembleInfo is no longer valid."
            except:
                raise gdb.GdbError(
                    "DisassembleInfo.read raised an unexpected exception"
                )

        print("PASS")


class GlobalNullDisassembler(TestDisassembler):
    """A disassembler that does not change the output at all."""

    def disassemble(self, info):
        pass


class ReadMemoryMemoryErrorDisassembler(TestDisassembler):
    """Raise a MemoryError exception from the DisassembleInfo.read_memory
    method."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            # Throw a memory error with a specific address.  We don't
            # expect this address to show up in the output though.
            raise gdb.MemoryError(0x1234)

    def disassemble(self, info):
        info = self.MyInfo(info)
        return builtin_disassemble_wrapper(info)


class ReadMemoryGdbErrorDisassembler(TestDisassembler):
    """Raise a GdbError exception from the DisassembleInfo.read_memory
    method."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            raise gdb.GdbError("read_memory raised GdbError")

    def disassemble(self, info):
        info = self.MyInfo(info)
        return builtin_disassemble_wrapper(info)


class ReadMemoryRuntimeErrorDisassembler(TestDisassembler):
    """Raise a RuntimeError exception from the DisassembleInfo.read_memory
    method."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            raise RuntimeError("read_memory raised RuntimeError")

    def disassemble(self, info):
        info = self.MyInfo(info)
        return builtin_disassemble_wrapper(info)


class ReadMemoryCaughtMemoryErrorDisassembler(TestDisassembler):
    """Raise a MemoryError exception from the DisassembleInfo.read_memory
    method, catch this in the outer disassembler."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            raise gdb.MemoryError(0x1234)

    def disassemble(self, info):
        info = self.MyInfo(info)
        try:
            return builtin_disassemble_wrapper(info)
        except gdb.MemoryError:
            return None


class ReadMemoryCaughtGdbErrorDisassembler(TestDisassembler):
    """Raise a GdbError exception from the DisassembleInfo.read_memory
    method, catch this in the outer disassembler."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            raise gdb.GdbError("exception message")

    def disassemble(self, info):
        info = self.MyInfo(info)
        try:
            return builtin_disassemble_wrapper(info)
        except gdb.GdbError as e:
            if e.args[0] == "exception message":
                return None
            raise e


class ReadMemoryCaughtRuntimeErrorDisassembler(TestDisassembler):
    """Raise a RuntimeError exception from the DisassembleInfo.read_memory
    method, catch this in the outer disassembler."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            raise RuntimeError("exception message")

    def disassemble(self, info):
        info = self.MyInfo(info)
        try:
            return builtin_disassemble_wrapper(info)
        except RuntimeError as e:
            if e.args[0] == "exception message":
                return None
            raise e


class MemorySourceNotABufferDisassembler(TestDisassembler):
    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            return 1234

    def disassemble(self, info):
        info = self.MyInfo(info)
        return builtin_disassemble_wrapper(info)


class MemorySourceBufferTooLongDisassembler(TestDisassembler):
    """The read memory returns too many bytes."""

    class MyInfo(gdb.disassembler.DisassembleInfo):
        def __init__(self, info):
            super().__init__(info)

        def read_memory(self, length, offset):
            buffer = super().read_memory(length, offset)
            # Create a new memory view made by duplicating BUFFER.  This
            # will trigger an error as GDB expects a buffer of exactly
            # LENGTH to be returned, while this will return a buffer of
            # 2*LENGTH.
            return memoryview(
                bytes([int.from_bytes(x, "little") for x in (list(buffer[0:]) * 2)])
            )

    def disassemble(self, info):
        info = self.MyInfo(info)
        return builtin_disassemble_wrapper(info)


class ErrorCreatingTextPart_NoArgs(TestDisassembler):
    """Try to create a DisassemblerTextPart with no arguments."""

    def disassemble(self, info):
        part = info.text_part()
        return None


class ErrorCreatingAddressPart_NoArgs(TestDisassembler):
    """Try to create a DisassemblerAddressPart with no arguments."""

    def disassemble(self, info):
        part = info.address_part()
        return None


class ErrorCreatingTextPart_NoString(TestDisassembler):
    """Try to create a DisassemblerTextPart with no string argument."""

    def disassemble(self, info):
        part = info.text_part(gdb.disassembler.STYLE_TEXT)
        return None


class ErrorCreatingTextPart_NoStyle(TestDisassembler):
    """Try to create a DisassemblerTextPart with no string argument."""

    def disassemble(self, info):
        part = info.text_part(string="abc")
        return None


class ErrorCreatingTextPart_StringAndParts(TestDisassembler):
    """Try to create a DisassemblerTextPart with both a string and a parts list."""

    def disassemble(self, info):
        parts = []
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, "p1"))
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, "p2"))

        return DisassemblerResult(length=4, string="p1p2", parts=parts)


class All_Text_Part_Styles(TestDisassembler):
    """Create text parts with all styles."""

    def disassemble(self, info):
        parts = []
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, "p1"))
        parts.append(info.text_part(gdb.disassembler.STYLE_MNEMONIC, "p2"))
        parts.append(info.text_part(gdb.disassembler.STYLE_SUB_MNEMONIC, "p3"))
        parts.append(info.text_part(gdb.disassembler.STYLE_ASSEMBLER_DIRECTIVE, "p4"))
        parts.append(info.text_part(gdb.disassembler.STYLE_REGISTER, "p5"))
        parts.append(info.text_part(gdb.disassembler.STYLE_IMMEDIATE, "p6"))
        parts.append(info.text_part(gdb.disassembler.STYLE_ADDRESS, "p7"))
        parts.append(info.text_part(gdb.disassembler.STYLE_ADDRESS_OFFSET, "p8"))
        parts.append(info.text_part(gdb.disassembler.STYLE_SYMBOL, "p9"))
        parts.append(info.text_part(gdb.disassembler.STYLE_COMMENT_START, "p10"))

        result = builtin_disassemble_wrapper(info)
        result = DisassemblerResult(length=result.length, parts=parts)

        tmp_str = ""
        for p in parts:
            assert p.string == str(p)
            tmp_str += str(p)
        assert tmp_str == result.string

        return result


class Build_Result_Using_All_Parts(TestDisassembler):
    """Disassemble an instruction and return a result that makes use of
    text and address parts."""

    def disassemble(self, info):
        global current_pc

        parts = []
        parts.append(info.text_part(gdb.disassembler.STYLE_MNEMONIC, "fake"))
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, "\t"))
        parts.append(info.text_part(gdb.disassembler.STYLE_REGISTER, "reg"))
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, ", "))
        addr_part = info.address_part(current_pc)
        assert addr_part.address == current_pc
        parts.append(addr_part)
        parts.append(info.text_part(gdb.disassembler.STYLE_TEXT, ", "))
        parts.append(info.text_part(gdb.disassembler.STYLE_IMMEDIATE, "123"))

        result = builtin_disassemble_wrapper(info)
        result = DisassemblerResult(length=result.length, parts=parts)
        return result


class BuiltinDisassembler(Disassembler):
    """Just calls the builtin disassembler."""

    def __init__(self):
        super().__init__("BuiltinDisassembler")

    def __call__(self, info):
        return builtin_disassemble_wrapper(info)


class AnalyzingDisassembler(Disassembler):
    class MyInfo(gdb.disassembler.DisassembleInfo):
        """Wrapper around builtin DisassembleInfo type that overrides the
        read_memory method."""

        def __init__(self, info, start, end, nop_bytes):
            """INFO is the DisassembleInfo we are wrapping.  START and END are
            addresses, and NOP_BYTES should be a memoryview object.

            The length (END - START) should be the same as the length
            of NOP_BYTES.

            Any memory read requests outside the START->END range are
            serviced normally, but any attempt to read within the
            START->END range will return content from NOP_BYTES."""
            super().__init__(info)
            self._start = start
            self._end = end
            self._nop_bytes = nop_bytes

        def _read_replacement(self, length, offset):
            """Return a slice of the buffer representing the replacement nop
            instructions."""

            assert self._nop_bytes is not None
            rb = self._nop_bytes

            # If this request is outside of a nop instruction then we don't know
            # what to do, so just raise a memory error.
            if offset >= len(rb) or (offset + length) > len(rb):
                raise gdb.MemoryError("invalid length and offset combination")

            # Return only the slice of the nop instruction as requested.
            s = offset
            e = offset + length
            return rb[s:e]

        def read_memory(self, length, offset=0):
            """Callback used by the builtin disassembler to read the contents of
            memory."""

            # If this request is within the region we are replacing with 'nop'
            # instructions, then call the helper function to perform that
            # replacement.
            if self._start is not None:
                assert self._end is not None
                if self.address >= self._start and self.address < self._end:
                    return self._read_replacement(length, offset)

            # Otherwise, we just forward this request to the default read memory
            # implementation.
            return super().read_memory(length, offset)

    def __init__(self):
        """Constructor."""
        super().__init__("AnalyzingDisassembler")

        # Details about the instructions found during the first disassembler
        # pass.
        self._pass_1_length = []
        self._pass_1_insn = []
        self._pass_1_address = []

        # The start and end address for the instruction we will replace with
        # one or more 'nop' instructions during pass two.
        self._start = None
        self._end = None

        # The index in the _pass_1_* lists for where the nop instruction can
        # be found, also, the buffer of bytes that make up a nop instruction.
        self._nop_index = None
        self._nop_bytes = None

        # A flag that indicates if we are in the first or second pass of
        # this disassembler test.
        self._first_pass = True

        # The disassembled instructions collected during the second pass.
        self._pass_2_insn = []

        # A copy of _pass_1_insn that has been modified to include the extra
        # 'nop' instructions we plan to insert during the second pass.  This
        # is then checked against _pass_2_insn after the second disassembler
        # pass has completed.
        self._check = []

    def __call__(self, info):
        """Called to perform the disassembly."""

        # Override the info object, this provides access to our
        # read_memory function.
        info = self.MyInfo(info, self._start, self._end, self._nop_bytes)
        result = builtin_disassemble_wrapper(info)

        # Record some informaiton about the first 'nop' instruction we find.
        if self._nop_index is None and is_nop(result.string):
            self._nop_index = len(self._pass_1_length)
            # The offset in the following read_memory call defaults to 0.
            self._nop_bytes = info.read_memory(result.length)

        # Record information about each instruction that is disassembled.
        # This test is performed in two passes, and we need different
        # information in each pass.
        if self._first_pass:
            self._pass_1_length.append(result.length)
            self._pass_1_insn.append(result.string)
            self._pass_1_address.append(info.address)
        else:
            self._pass_2_insn.append(result.string)

        return result

    def find_replacement_candidate(self):
        """Call this after the first disassembly pass.  This identifies a suitable
        instruction to replace with 'nop' instruction(s)."""

        if self._nop_index is None:
            raise gdb.GdbError("no nop was found")

        nop_idx = self._nop_index
        nop_length = self._pass_1_length[nop_idx]

        # First we look for an instruction that is larger than a nop
        # instruction, but whose length is an exact multiple of the nop
        # instruction's length.
        replace_idx = None
        for idx in range(len(self._pass_1_length)):
            if (
                idx > 0
                and idx != nop_idx
                and not is_nop(self._pass_1_insn[idx])
                and self._pass_1_length[idx] > self._pass_1_length[nop_idx]
                and self._pass_1_length[idx] % self._pass_1_length[nop_idx] == 0
            ):
                replace_idx = idx
                break

        # If we still don't have a replacement candidate, then search again,
        # this time looking for an instruciton that is the same length as a
        # nop instruction.
        if replace_idx is None:
            for idx in range(len(self._pass_1_length)):
                if (
                    idx > 0
                    and idx != nop_idx
                    and not is_nop(self._pass_1_insn[idx])
                    and self._pass_1_length[idx] == self._pass_1_length[nop_idx]
                ):
                    replace_idx = idx
                    break

        # Weird, the nop instruction must be larger than every other
        # instruction, or all instructions are 'nop'?
        if replace_idx is None:
            raise gdb.GdbError("can't find an instruction to replace")

        # Record the instruction range that will be replaced with 'nop'
        # instructions, and mark that we are now on the second pass.
        self._start = self._pass_1_address[replace_idx]
        self._end = self._pass_1_address[replace_idx] + self._pass_1_length[replace_idx]
        self._first_pass = False
        print("Replace from 0x%x to 0x%x with NOP" % (self._start, self._end))

        # Finally, build the expected result.  Create the _check list, which
        # is a copy of _pass_1_insn, but replace the instruction we
        # identified above with a series of 'nop' instructions.
        self._check = list(self._pass_1_insn)
        nop_count = int(self._pass_1_length[replace_idx] / self._pass_1_length[nop_idx])
        nop_insn = self._pass_1_insn[nop_idx]
        nops = [nop_insn] * nop_count
        self._check[replace_idx : (replace_idx + 1)] = nops

    def check(self):
        """Call this after the second disassembler pass to validate the output."""
        if self._check != self._pass_2_insn:
            raise gdb.GdbError("mismatch")
        print("PASS")


def add_global_disassembler(dis_class):
    """Create an instance of DIS_CLASS and register it as a global disassembler."""
    dis = dis_class()
    gdb.disassembler.register_disassembler(dis, None)
    return dis


class InvalidDisassembleInfo(gdb.disassembler.DisassembleInfo):
    """An attempt to create a DisassembleInfo sub-class without calling
    the parent class init method.

    Attempts to use instances of this class should throw an error
    saying that the DisassembleInfo is not valid, despite this class
    having all of the required attributes.

    The reason why this class will never be valid is that an internal
    field (within the C++ code) can't be initialized without calling
    the parent class init method."""

    def __init__(self):
        assert current_pc is not None

    def is_valid(self):
        return True

    @property
    def address(self):
        global current_pc
        return current_pc

    @property
    def architecture(self):
        return gdb.selected_inferior().architecture()

    @property
    def progspace(self):
        return gdb.selected_inferior().progspace


# Start with all disassemblers removed.
remove_all_python_disassemblers()

print("Python script imported")
