예제 #1
0
 def __init__(self, encoding, length, instructionSet):
     self.length = length
     self.encoding = encoding
     self.instructionSet = instructionSet
     self.condition = Condition(Condition.AL)
     self.width = ''
     self.shiftType = 0
     self.shiftAmount = Constant(0)
예제 #2
0
 def setShift(self, shiftTypeAndAmount):
     'Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``.'
     self.shiftType = shiftTypeAndAmount[0]
     shiftAmount = shiftTypeAndAmount[1]
     if not isinstance(shiftAmount, Operand):
         shiftAmount = Constant(shiftAmount)
     self.shiftAmount = shiftAmount
     return self
예제 #3
0
 def __init__(self, encoding, length, instructionSet):
     self.length = length
     self.encoding = encoding
     self.instructionSet = instructionSet
     self.condition = Condition(Condition.AL)
     self.width = ""
     self.shiftType = 0
     self.shiftAmount = Constant(0)
예제 #4
0
class Instruction(metaclass=ABCMeta):
    '''
    The base class for all ARM and Thumb instructions.

    .. attribute:: encoding

        The encoding (as a little-endian integer) of this instruction.

    .. attribute:: length

        The length of this instruction.

    .. attribute:: instructionSet

        The instruction set of this instruction.

        +-------+-----------------+
        | Value | Instruction set |
        +=======+=================+
        | 0     | ARM             |
        +-------+-----------------+
        | 1     | Thumb           |
        +-------+-----------------+
        | 2     | Jazelle         |
        +-------+-----------------+
        | 3     | ThumbEE         |
        +-------+-----------------+

    .. attribute:: condition

        The :class:`Condition` of this instruction.

    .. attribute:: width

        The instruction width. This field only affects the disassembly.

        +----------+--------------+
        | Width    | Meaning      |
        +==========+==============+
        | ``''``   | Default      |
        +----------+--------------+
        | ``'.n'`` | Force narrow |
        +----------+--------------+
        | ``'.w'`` | Force wide   |
        +----------+--------------+

    .. attribute:: shiftType
        shiftAmount

        The shift type and amount to be applied to the last operand.

        +--------------------------------------------+---------------------------------+
        | Shift type                                 | Meaning                         |
        +============================================+=================================+
        | :const:`~cpu.arm.functions.SRTYPE_LSL` (0) | Left shift                      |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_LSR` (1) | Logical (unsigned) right shift  |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_ASR` (2) | Arithmetic (signed) right shift |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_ROR` (3) | Rotate bits right               |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_RRX` (4) | Rotate bits right with carry    |
        +--------------------------------------------+---------------------------------+

    '''
    def __init__(self, encoding, length, instructionSet):
        self.length = length
        self.encoding = encoding
        self.instructionSet = instructionSet
        self.condition = Condition(Condition.AL)
        self.width = ''
        self.shiftType = 0
        self.shiftAmount = Constant(0)

    @abstractmethod
    def mainOpcode(self):  # pragma: no cover
        "Return the instruction's opcode without conditions."
        return '<unk{0:0{1}x}>'.format(self.encoding, self.length * 2)

    @property
    def opcode(self):
        '''Return the instruction's opcode (including condition code).

        Subclasses should overload the :meth:`mainOpcode` method to provide the
        actual opcode.'''
        return self.mainOpcode() + str(self.condition) + self.width

    def forceWide(self):
        '''Force the ".w" qualifier to show in the disassembly of this
        instruction. Returns ``self``.'''
        self.width = '.w'
        return self

    def setShift(self, shiftTypeAndAmount):
        'Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``.'
        self.shiftType = shiftTypeAndAmount[0]
        shiftAmount = shiftTypeAndAmount[1]
        if not isinstance(shiftAmount, Operand):
            shiftAmount = Constant(shiftAmount)
        self.shiftAmount = shiftAmount
        return self

    def execute(self, thread):
        'Execute the instruction with a *thread*'
        location = thread.pcRaw
        if self.condition.check(thread.cpsr):
            self.exec(thread)
            if thread.pcRaw != location:
                thread.onBranch(location, self, thread)
                return
        thread.pc = location + self.length

    @abstractmethod
    def exec(self, thread):  # pragma: no cover
        '''Execute the instruction with a *thread* after passing the conditions.

        Subclasses should override this method to provide the actual
        implementation of this instruction.'''
        assert False

    @abstractproperty
    def operands(self):  # pragma: no cover
        'Return a list of :class:`~cpu.arm.operand.Operand`\s of the instruction.'
        return []

    def applyShift(self, thread, value, carry):
        'Apply shift to an integer. Return the shifted value.'
        return Shift(0xffffffff, value, self.shiftType,
                     self.shiftAmount.get(thread), carry)

    def applyShift_C(self, thread, value, carry):
        'Apply shift to an integer. Return the shifted value and carry.'
        return Shift_C(0xffffffff, value, self.shiftType,
                       self.shiftAmount.get(thread), carry)

    def __str__(self):
        'Disassemble this instruction.'
        opcode = self.opcode
        operands = ', '.join(map(str, self.operands))
        if self.shiftType or self.shiftAmount:
            operands += _formatShift(self.shiftType, self.shiftAmount)
        return '{0}\t{1}'.format(opcode, operands)
예제 #5
0
class Instruction(metaclass=ABCMeta):
    """
    The base class for all ARM and Thumb instructions.

    .. attribute:: encoding

        The encoding (as a little-endian integer) of this instruction.

    .. attribute:: length

        The length of this instruction.

    .. attribute:: instructionSet

        The instruction set of this instruction.

        +-------+-----------------+
        | Value | Instruction set |
        +=======+=================+
        | 0     | ARM             |
        +-------+-----------------+
        | 1     | Thumb           |
        +-------+-----------------+
        | 2     | Jazelle         |
        +-------+-----------------+
        | 3     | ThumbEE         |
        +-------+-----------------+

    .. attribute:: condition

        The :class:`Condition` of this instruction.

    .. attribute:: width

        The instruction width. This field only affects the disassembly.

        +----------+--------------+
        | Width    | Meaning      |
        +==========+==============+
        | ``''``   | Default      |
        +----------+--------------+
        | ``'.n'`` | Force narrow |
        +----------+--------------+
        | ``'.w'`` | Force wide   |
        +----------+--------------+

    .. attribute:: shiftType
        shiftAmount

        The shift type and amount to be applied to the last operand.

        +--------------------------------------------+---------------------------------+
        | Shift type                                 | Meaning                         |
        +============================================+=================================+
        | :const:`~cpu.arm.functions.SRTYPE_LSL` (0) | Left shift                      |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_LSR` (1) | Logical (unsigned) right shift  |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_ASR` (2) | Arithmetic (signed) right shift |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_ROR` (3) | Rotate bits right               |
        +--------------------------------------------+---------------------------------+
        | :const:`~cpu.arm.functions.SRTYPE_RRX` (4) | Rotate bits right with carry    |
        +--------------------------------------------+---------------------------------+

    """

    def __init__(self, encoding, length, instructionSet):
        self.length = length
        self.encoding = encoding
        self.instructionSet = instructionSet
        self.condition = Condition(Condition.AL)
        self.width = ""
        self.shiftType = 0
        self.shiftAmount = Constant(0)

    @abstractmethod
    def mainOpcode(self):  # pragma: no cover
        "Return the instruction's opcode without conditions."
        return "<unk{0:0{1}x}>".format(self.encoding, self.length * 2)

    @property
    def opcode(self):
        """Return the instruction's opcode (including condition code).

        Subclasses should overload the :meth:`mainOpcode` method to provide the
        actual opcode."""
        return self.mainOpcode() + str(self.condition) + self.width

    def forceWide(self):
        """Force the ".w" qualifier to show in the disassembly of this
        instruction. Returns ``self``."""
        self.width = ".w"
        return self

    def setShift(self, shiftTypeAndAmount):
        "Set the :attr:`shiftType` and :attr:`shiftAmount`. Returns ``self``."
        self.shiftType = shiftTypeAndAmount[0]
        shiftAmount = shiftTypeAndAmount[1]
        if not isinstance(shiftAmount, Operand):
            shiftAmount = Constant(shiftAmount)
        self.shiftAmount = shiftAmount
        return self

    def execute(self, thread):
        "Execute the instruction with a *thread*"
        location = thread.pcRaw
        if self.condition.check(thread.cpsr):
            self.exec(thread)
            if thread.pcRaw != location:
                thread.onBranch(location, self, thread)
                return
        thread.pc = location + self.length

    @abstractmethod
    def exec(self, thread):  # pragma: no cover
        """Execute the instruction with a *thread* after passing the conditions.

        Subclasses should override this method to provide the actual
        implementation of this instruction."""
        assert False

    @abstractproperty
    def operands(self):  # pragma: no cover
        "Return a list of :class:`~cpu.arm.operand.Operand`\s of the instruction."
        return []

    def applyShift(self, thread, value, carry):
        "Apply shift to an integer. Return the shifted value."
        return Shift(0xFFFFFFFF, value, self.shiftType, self.shiftAmount.get(thread), carry)

    def applyShift_C(self, thread, value, carry):
        "Apply shift to an integer. Return the shifted value and carry."
        return Shift_C(0xFFFFFFFF, value, self.shiftType, self.shiftAmount.get(thread), carry)

    def __str__(self):
        "Disassemble this instruction."
        opcode = self.opcode
        operands = ", ".join(map(str, self.operands))
        if self.shiftType or self.shiftAmount:
            operands += _formatShift(self.shiftType, self.shiftAmount)
        return "{0}\t{1}".format(opcode, operands)