<commit_before># Copyright (c) 2014, Fundacion Dr. <NAME>
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
This modules contains a ARM disassembler based on the Capstone
disassembly framework.

"""
import logging

from capstone import CS_MODE_ARM
from capstone import CS_MODE_THUMB
from capstone import Cs
from capstone import CS_ARCH_ARM
from capstone.arm import ARM_CC_EQ
from capstone.arm import ARM_CC_NE
from capstone.arm import ARM_CC_MI
from capstone.arm import ARM_CC_PL
from capstone.arm import ARM_CC_VS
from capstone.arm import ARM_CC_VC
from capstone.arm import ARM_CC_HI
from capstone.arm import ARM_CC_LS
from capstone.arm import ARM_CC_GE
from capstone.arm import ARM_CC_LT
from capstone.arm import ARM_CC_GT
from capstone.arm import ARM_CC_LE
from capstone.arm import ARM_CC_AL
from capstone.arm import ARM_CC_HS
from capstone.arm import ARM_CC_LO
from capstone.arm import ARM_SFT_ASR
from capstone.arm import ARM_SFT_LSL
from capstone.arm import ARM_SFT_LSR
from capstone.arm import ARM_SFT_ROR
from capstone.arm import ARM_SFT_RRX
from capstone.arm import ARM_SFT_ASR_REG
from capstone.arm import ARM_SFT_LSL_REG
from capstone.arm import ARM_SFT_LSR_REG
from capstone.arm import ARM_SFT_ROR_REG
from capstone.arm import ARM_SFT_RRX_REG
from capstone.arm import ARM_OP_REG
from capstone.arm import ARM_OP_IMM
from capstone.arm import ARM_OP_MEM
from capstone.arm import ARM_CC_INVALID


from barf.arch import ARCH_ARM_MODES_MAX
from barf.arch import ARCH_ARM_MODE_32
from barf.arch import ARCH_ARM_MODE_ARM
from barf.arch import ARCH_ARM_MODE_THUMB
from barf.arch.arm.armbase import ARM_COND_CODE_EQ
from barf.arch.arm.armbase import ARM_COND_CODE_NE
from barf.arch.arm.armbase import ARM_COND_CODE_MI
from barf.arch.arm.armbase import ARM_COND_CODE_PL
from barf.arch.arm.armbase import ARM_COND_CODE_VS
from barf.arch.arm.armbase import ARM_COND_CODE_VC
from barf.arch.arm.armbase import ARM_COND_CODE_HI
from barf.arch.arm.armbase import ARM_COND_CODE_LS
from barf.arch.arm.armbase import ARM_COND_CODE_GE
from barf.arch.arm.armbase import ARM_COND_CODE_LT
from barf.arch.arm.armbase import ARM_COND_CODE_GT
from barf.arch.arm.armbase import ARM_COND_CODE_LE
from barf.arch.arm.armbase import ARM_COND_CODE_AL
from barf.arch.arm.armbase import ARM_COND_CODE_HS
from barf.arch.arm.armbase import ARM_COND_CODE_LO
from barf.arch.arm.armbase import ArmInstruction
from barf.arch.arm.armbase import ArmRegisterListOperand
from barf.arch.arm.armbase import ArmImmediateOperand
from barf.arch.arm.armbase import ArmMemoryOperand
from barf.arch.arm.armbase import CapstoneOperandNotSupported
from barf.arch.arm.armbase import InvalidDisassemblerData
from barf.arch.arm.armbase import ArmRegisterOperand
from barf.arch.arm.armbase import ArmShiftedRegisterOperand
from barf.arch.arm.armbase import ArmArchitectureInformation
from barf.arch.arm.armbase import ARM_MEMORY_INDEX_OFFSET
from barf.arch.arm.armbase import cc_inverse_mapper
from barf.arch.arm.armparser import ArmParser
from barf.core.disassembler import Disassembler

cc_capstone_barf_mapper = {
    ARM_CC_EQ : ARM_COND_CODE_EQ,
    ARM_CC_NE : ARM_COND_CODE_NE,
    ARM_CC_MI : ARM_COND_CODE_MI,
    ARM_CC_PL : ARM_COND_CODE_PL,
    ARM_CC_VS : ARM_COND_CODE_VS,
    ARM_CC_VC : ARM_COND_CODE_VC,
    ARM_CC_HI : ARM_COND_CODE_HI,
    ARM_CC_LS : ARM_COND_CODE_LS,
    ARM_CC_GE : ARM_COND_CODE_GE,
    ARM_CC_LT : ARM_COND_CODE_LT,
    ARM_CC_GT : ARM_COND_CODE_GT,
    ARM_CC_LE : ARM_COND_CODE_LE,
    ARM_CC_AL : ARM_COND_CODE_AL,
    ARM_CC_HS : ARM_COND_CODE_HS,
    ARM_CC_LO : ARM_COND_CODE_LO,
}

arch_mode_barf_to_capstone_mapper = {
    ARCH_ARM_MODE_ARM : CS_MODE_ARM,
    ARCH_ARM_MODE_THUMB : CS_MODE_THUMB,
}

logger = logging.getLogger(__name__)


class ArmDisassembler(Disassembler):
    """ARM Disassembler.
    """

    def __init__(self, architecture_mode=ARCH_ARM_MODE_32):
        super(ArmDisassembler, self).__init__()

        self._architecture_mode = architecture_mode
        self._arch_info = ArmArchitectureInformation(architecture_mode)

#         arch_mode_map = {
#             # TODO: ARM vs CS_MODE_THUMB
#             ARCH_ARM_MODE_32 : CS_MODE_THUMB,
#         }

        self._parser = ArmParser(architecture_mode)

        self._avaliable_disassemblers = [None] * ARCH_ARM_MODES_MAX
        self._avaliable_disassemblers[ARCH_ARM_MODE_ARM] = Cs(CS_ARCH_ARM, arch_mode_barf_to_capstone_mapper[ARCH_ARM_MODE_ARM])
        self._avaliable_disassemblers[ARCH_ARM_MODE_THUMB] = Cs(CS_ARCH_ARM, arch_mode_barf_to_capstone_mapper[ARCH_ARM_MODE_THUMB])
        # TODO: DECOUPLE: detail true vs false
        self._avaliable_disassemblers[ARCH_ARM_MODE_ARM].detail = True
        self._avaliable_disassemblers[ARCH_ARM_MODE_THUMB].detail = True

        # TODO: define default disassembler externally
        self._disassembler = self._avaliable_disassemblers[1]

    def _cs_reg_idx_to_arm_op_reg(self, cs_reg_idx, cs_insn):
        name = cs_insn.reg_name(cs_reg_idx)
        if name in self._arch_info.registers_size:
            size = self._arch_info.registers_size[name]
        else:
            size = self._arch_info.architecture_size
        return ArmRegisterOperand(name, size)

    def _cs_shift_to_arm_op(self, cs_op, cs_insn, arm_base):

        if cs_op.shift.type == 0:
            raise Exception("_cs_shift_to_arm_op: Invalid shift type")

        cs_shift_mapper = {
            ARM_SFT_ASR : "asr",
            ARM_SFT_LSL : "lsl",
            ARM_SFT_LSR : "lsr",
            ARM_SFT_ROR : "ror",
            ARM_SFT_RRX : "rrx",
            ARM_SFT_ASR_REG : "asr",
            ARM_SFT_LSL_REG : "lsl",
            ARM_SFT_LSR_REG : "lsr",
            ARM_SFT_ROR_REG : "ror",
            ARM_SFT_RRX_REG : "rrx",
        }
        # The base register (arm_base) is not included in the shift struct in Capstone, so it's provided separately
        sh_type = cs_shift_mapper[cs_op.shift.type]

        if cs_op.shift.type <= ARM_SFT_RRX:
            amount = ArmImmediateOperand(cs_op.shift.value, self._arch_info.operand_size)
            # TODO: check if this is a valid case
            if cs_op.shift.value == 0:
                raise Exception("_cs_shift_to_arm_op: shift value == 0")
        elif cs_op.shift.type <= ARM_SFT_RRX_REG:
            amount = self._cs_reg_idx_to_arm_op_reg(cs_op.shift.value, cs_insn)
        else:
            raise Exception("_cs_shift_to_arm_op: Unknown shift type.")

        return ArmShiftedRegisterOperand(arm_base, sh_type, amount, arm_base.size)


    def _cs_translate_operand(self, cs_op, cs_insn):

        if cs_op.type == ARM_OP_REG:
            oprnd = self._cs_reg_idx_to_arm_op_reg(cs_op.value.reg, cs_insn)

        elif cs_op.type == ARM_OP_IMM:
            size = self._arch_info.operand_size
            oprnd = ArmImmediateOperand(cs_op.value.imm, size)

        elif cs_op.type == ARM_OP_MEM:
            reg_base = self._cs_reg_idx_to_arm_op_reg(cs_op.mem.base, cs_insn)

            # TODO: memory index type
            index_type = ARM_MEMORY_INDEX_OFFSET

            if cs_op.mem.index > 0:

                if cs_op.mem.disp > 0:
                    raise Exception("ARM_OP_MEM: Both index and disp > 0, only one can be.")

                displacement = self._cs_reg_idx_to_arm_op_reg(cs_op.mem.index, cs_insn)<commit_msg>ARM: Translator: Shifted register.<commit_after># Copyright (c) 2014, Fundacion Dr. <NAME>
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""
This modules contains a ARM disassembler based on the Capstone
disassembly framework.

"""
import logging

from capstone import CS_MODE_ARM
from capstone import CS_MODE_THUMB
from capstone import Cs
from capstone import CS_ARCH_ARM
from capstone.arm import ARM_CC_EQ
from capstone.arm import ARM_CC_NE
from capstone.arm import ARM_CC_MI
from capstone.arm import ARM_CC_PL
from capstone.arm import ARM_CC_VS
from capstone.arm import ARM_CC_VC
from capstone.arm import ARM_CC_HI
from capstone.arm import ARM_CC_LS
from capstone.arm import ARM_CC_GE
from capstone.arm import ARM_CC_LT
from capstone.arm import ARM_CC_GT
from capstone.arm import ARM_CC_LE
from capstone.arm import ARM_CC_AL
from capstone.arm import ARM_CC_HS
from capstone.arm import ARM_CC_LO
from capstone.arm import ARM_SFT_ASR
from capstone.arm import ARM_SFT_LSL
from capstone.arm import ARM_SFT_LSR
from capstone.arm import ARM_SFT_ROR
from capstone.arm import ARM_SFT_RRX
from capstone.arm import ARM_SFT_ASR_REG
from capstone.arm import ARM_SFT_LSL_REG
from capstone.arm import ARM_SFT_LSR_REG
from capstone.arm import ARM_SFT_ROR_REG
from capstone.arm import ARM_SFT_RRX_REG
from capstone.arm import ARM_OP_REG
from capstone.arm import ARM_OP_IMM
from capstone.arm import ARM_OP_MEM
from capstone.arm import ARM_CC_INVALID


from barf.arch import ARCH_ARM_MODES_MAX
from barf.arch import ARCH_ARM_MODE_32
from barf.arch import ARCH_ARM_MODE_ARM
from barf.arch import ARCH_ARM_MODE_THUMB
from barf.arch.arm.armbase import ARM_COND_CODE_EQ
from barf.arch.arm.armbase import ARM_COND_CODE_NE
from barf.arch.arm.armbase import ARM_COND_CODE_MI
from barf.arch.arm.armbase import ARM_COND_CODE_PL
from barf.arch.arm.armbase import ARM_COND_CODE_VS
from barf.arch.arm.armbase import ARM_COND_CODE_VC
from barf.arch.arm.armbase import ARM_COND_CODE_HI
from barf.arch.arm.armbase import ARM_COND_CODE_LS
from barf.arch.arm.armbase import ARM_COND_CODE_GE
from barf.arch.arm.armbase import ARM_COND_CODE_LT
from barf.arch.arm.armbase import ARM_COND_CODE_GT
from barf.arch.arm.armbase import ARM_COND_CODE_LE
from barf.arch.arm.armbase import ARM_COND_CODE_AL
from barf.arch.arm.armbase import ARM_COND_CODE_HS
from barf.arch.arm.armbase import ARM_COND_CODE_LO
from barf.arch.arm.armbase import ArmInstruction
from barf.arch.arm.armbase import ArmRegisterListOperand
from barf.arch.arm.armbase import ArmImmediateOperand
from barf.arch.arm.armbase import ArmMemoryOperand
from barf.arch.arm.armbase import CapstoneOperandNotSupported
from barf.arch.arm.armbase import InvalidDisassemblerData
from barf.arch.arm.armbase import ArmRegisterOperand
from barf.arch.arm.armbase import ArmShiftedRegisterOperand
from barf.arch.arm.armbase import ArmArchitectureInformation
from barf.arch.arm.armbase import ARM_MEMORY_INDEX_OFFSET
from barf.arch.arm.armbase import cc_inverse_mapper
from barf.arch.arm.armparser import ArmParser
from barf.core.disassembler import Disassembler

cc_capstone_barf_mapper = {
    ARM_CC_EQ : ARM_COND_CODE_EQ,
    ARM_CC_NE : ARM_COND_CODE_NE,
    ARM_CC_MI : ARM_COND_CODE_MI,
    ARM_CC_PL : ARM_COND_CODE_PL,
    ARM_CC_VS : ARM_COND_CODE_VS,
    ARM_CC_VC : ARM_COND_CODE_VC,
    ARM_CC_HI : ARM_COND_CODE_HI,
    ARM_CC_LS : ARM_COND_CODE_LS,
    ARM_CC_GE : ARM_COND_CODE_GE,
    ARM_CC_LT : ARM_COND_CODE_LT,
    ARM_CC_GT : ARM_COND_CODE_GT,
    ARM_CC_LE : ARM_COND_CODE_LE,
    ARM_CC_AL : ARM_COND_CODE_AL,
    ARM_CC_HS : ARM_COND_CODE_HS,
    ARM_CC_LO : ARM_COND_CODE_LO,
}

arch_mode_barf_to_capstone_mapper = {
    ARCH_ARM_MODE_ARM : CS_MODE_ARM,
    ARCH_ARM_MODE_THUMB : CS_MODE_THUMB,
}

logger = logging.getLogger(__name__)


class ArmDisassembler(Disassembler):
    """ARM Disassembler.
    """

    def __init__(self, architecture_mode=ARCH_ARM_MODE_32):
        super(ArmDisassembler, self).__init__()

        self._architecture_mode = architecture_mode
        self._arch_info = ArmArchitectureInformation(architecture_mode)

#         arch_mode_map = {
#             # TODO: ARM vs CS_MODE_THUMB
#             ARCH_ARM_MODE_32 : CS_MODE_THUMB,
#         }

        self._parser = ArmParser(architecture_mode)

        self._avaliable_disassemblers = [None] * ARCH_ARM_MODES_MAX
        self._avaliable_disassemblers[ARCH_ARM_MODE_ARM] = Cs(CS_ARCH_ARM, arch_mode_barf_to_capstone_mapper[ARCH_ARM_MODE_ARM])
        self._avaliable_disassemblers[ARCH_ARM_MODE_THUMB] = Cs(CS_ARCH_ARM, arch_mode_barf_to_capstone_mapper[ARCH_ARM_MODE_THUMB])
        # TODO: DECOUPLE: detail true vs false
        self._avaliable_disassemblers[ARCH_ARM_MODE_ARM].detail = True
        self._avaliable_disassemblers[ARCH_ARM_MODE_THUMB].detail = True

        # TODO: define default disassembler externally
        self._disassembler = self._avaliable_disassemblers[1]

    def _cs_reg_idx_to_arm_op_reg(self, cs_reg_idx, cs_insn):
        name = cs_insn.reg_name(cs_reg_idx)
        if name in self._arch_info.registers_size:
            size = self._arch_info.registers_size[name]
        else:
            size = self._arch_info.architecture_size
        return ArmRegisterOperand(name, size)

    def _cs_shift_to_arm_op(self, cs_op, cs_insn, arm_base):

        if cs_op.shift.type == 0:
            raise Exception("_cs_shift_to_arm_op: Invalid shift type")

        cs_shift_mapper = {
            ARM_SFT_ASR : "asr",
            ARM_SFT_LSL : "lsl",
            ARM_SFT_LSR : "lsr",
            ARM_SFT_ROR : "ror",
            ARM_SFT_RRX : "rrx",
            ARM_SFT_ASR_REG : "asr",
            ARM_SFT_LSL_REG : "lsl",
            ARM_SFT_LSR_REG : "lsr",
            ARM_SFT_ROR_REG : "ror",
            ARM_SFT_RRX_REG : "rrx",
        }
        # The base register (arm_base) is not included in the shift struct in Capstone, so it's provided separately
        sh_type = cs_shift_mapper[cs_op.shift.type]

        if cs_op.shift.type <= ARM_SFT_RRX:
            amount = ArmImmediateOperand(cs_op.shift.value, self._arch_info.operand_size)
            # TODO: check if this is a valid case
            if cs_op.shift.value == 0:
                raise Exception("_cs_shift_to_arm_op: shift value == 0")
        elif cs_op.shift.type <= ARM_SFT_RRX_REG:
            amount = self._cs_reg_idx_to_arm_op_reg(cs_op.shift.value, cs_insn)
        else:
            raise Exception("_cs_shift_to_arm_op: Unknown shift type.")

        return ArmShiftedRegisterOperand(arm_base, sh_type, amount, arm_base.size)


    def _cs_translate_operand(self, cs_op, cs_insn):

        if cs_op.type == ARM_OP_REG:
            reg = self._cs_reg_idx_to_arm_op_reg(cs_op.value.reg, cs_insn)
            if cs_op.shift.type > 0:
                displacement = self._cs_shift_to_arm_op(cs_op, cs_insn, reg)
                oprnd = displacement
            else:
                oprnd = reg


        elif cs_op.type == ARM_OP_IMM:
            size = self._arch_info.operand_size
            oprnd = ArmImmediateOperand(cs_op.value.imm, size)

        elif cs_op.type == ARM_OP_MEM:
            reg_base = self._cs_reg_idx_to_arm_op_reg(cs_op.mem.base, cs_insn)

            # TODO: memory index type
            index_type = ARM_MEMORY_INDEX_OFFSET

            if cs_op.mem.index > 0:

                if cs_op.mem.disp > 0:
                    raise Exception("ARM_OP_MEM: Both index and disp > 0, only one can be.")

                displacement = self._cs_reg_idx_to_arm_op_reg(cs_op.mem.index, cs_insn)
{'fraction_non_alphanumeric': 0.0617903049167099, 'fraction_numerical': 0.0022479681826041847, 'mean_word_length': 3.780931386056765, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3088789', 'n_tokens_mistral': 6058, 'n_tokens_neox': 5891, 'n_words': 1444}