# Copyright (C) 2021-2024 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 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")
