예제 #1
0
class X86Translator(Translator):
    """x86 to IR Translator."""
    def __init__(self, architecture_mode):

        super(X86Translator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = X86ArchitectureInformation(architecture_mode)

        # An instance of a *VariableNamer*. This is used so all the
        # temporary REIL registers are unique.
        self._ir_name_generator = VariableNamer("t", separator="")

        self._builder = ReilBuilder()

        self._flags = {
            "af": ReilRegisterOperand("af", 1),
            "cf": ReilRegisterOperand("cf", 1),
            "df": ReilRegisterOperand("df", 1),
            "of": ReilRegisterOperand("of", 1),
            "pf": ReilRegisterOperand("pf", 1),
            "sf": ReilRegisterOperand("sf", 1),
            "zf": ReilRegisterOperand("zf", 1),
        }

        if self._arch_mode == ARCH_X86_MODE_32:
            self._sp = ReilRegisterOperand("esp", 32)
            self._bp = ReilRegisterOperand("ebp", 32)
            self._ip = ReilRegisterOperand("eip", 32)

            self._ws = ReilImmediateOperand(4, 32)  # word size
        elif self._arch_mode == ARCH_X86_MODE_64:
            self._sp = ReilRegisterOperand("rsp", 64)
            self._bp = ReilRegisterOperand("rbp", 64)
            self._ip = ReilRegisterOperand("rip", 64)

            self._ws = ReilImmediateOperand(8, 64)  # word size

    def translate(self, instruction):
        """Return IR representation of an instruction.
        """
        try:
            trans_instrs = self.__translate(instruction)
        except NotImplementedError:
            unkn_instr = self._builder.gen_unkn()
            unkn_instr.address = instruction.address << 8 | (0x0 & 0xff)
            trans_instrs = [unkn_instr]

            self.__log_not_supported_instruction(instruction)
        except:
            self.__log_translation_exception(instruction)

            raise

        return trans_instrs

    def reset(self):
        """Restart IR register name generator.
        """
        self._ir_name_generator.reset()

    def __translate(self, instruction):
        """Translate a x86 instruction into REIL language.

        :param instruction: a x86 instruction
        :type instruction: X86Instruction
        """
        # Retrieve translation function.
        mnemonic = instruction.mnemonic

        # Check whether it refers to the strings instruction or the sse instruction.
        if instruction.mnemonic in ["movsd"]:
            if instruction.bytes[0] not in ["\xa4", "\xa5"]:
                mnemonic += "_sse"

        # Translate instruction.
        if mnemonic in translators.dispatcher:
            tb = X86TranslationBuilder(self._ir_name_generator,
                                       self._arch_mode)

            translators.dispatcher[mnemonic](self, tb, instruction)
        else:
            raise NotImplementedError("Instruction Not Implemented")

        return tb.instanciate(instruction.address)

    def __log_not_supported_instruction(self, instruction):
        bytes_str = " ".join("%02x" % ord(b) for b in instruction.bytes)

        logger.info("Instruction not supported: %s (%s [%s])",
                    instruction.mnemonic, instruction, bytes_str)

    def __log_translation_exception(self, instruction):
        bytes_str = " ".join("%02x" % ord(b) for b in instruction.bytes)

        logger.error("Failed to translate x86 to REIL: %s (%s)",
                     instruction,
                     bytes_str,
                     exc_info=True)

    # Flag translation.
    # ======================================================================== #
    def _update_af(self, tb, oprnd0, oprnd1, result):
        assert oprnd0.size == oprnd1.size

        tmp0 = tb.temporal(8)
        tmp1 = tb.temporal(8)
        tmp2 = tb.temporal(8)
        tmp3 = tb.temporal(8)
        tmp4 = tb.temporal(8)
        tmp5 = tb.temporal(8)
        tmp6 = tb.temporal(8)

        imm4 = tb.immediate(4, 8)
        immn4 = tb.immediate(-4, 8)

        af = self._flags["af"]

        # Extract lower byte.
        tb.add(self._builder.gen_str(oprnd0, tmp0))
        tb.add(self._builder.gen_str(oprnd1, tmp1))

        # Zero-extend lower 4 bits.
        tb.add(self._builder.gen_bsh(tmp0, imm4, tmp2))
        tb.add(self._builder.gen_bsh(tmp2, immn4, tmp4))

        tb.add(self._builder.gen_bsh(tmp1, imm4, tmp3))
        tb.add(self._builder.gen_bsh(tmp3, immn4, tmp5))

        # Add up.
        tb.add(self._builder.gen_add(tmp4, tmp5, tmp6))

        # Move bit 4 to AF flag.
        tb.add(self._builder.gen_bsh(tmp6, immn4, af))

    def _update_af_sub(self, tb, oprnd0, oprnd1, result):
        assert oprnd0.size == oprnd1.size

        tmp0 = tb.temporal(8)
        tmp1 = tb.temporal(8)
        tmp2 = tb.temporal(8)
        tmp3 = tb.temporal(8)
        tmp4 = tb.temporal(8)
        tmp5 = tb.temporal(8)
        tmp6 = tb.temporal(8)

        imm4 = tb.immediate(4, 8)
        immn4 = tb.immediate(-4, 8)

        af = self._flags["af"]

        # Extract lower byte.
        tb.add(self._builder.gen_str(oprnd0, tmp0))
        tb.add(self._builder.gen_str(oprnd1, tmp1))

        # Zero-extend lower 4 bits.
        tb.add(self._builder.gen_bsh(tmp0, imm4, tmp2))
        tb.add(self._builder.gen_bsh(tmp2, immn4, tmp4))

        tb.add(self._builder.gen_bsh(tmp1, imm4, tmp3))
        tb.add(self._builder.gen_bsh(tmp3, immn4, tmp5))

        # Subtract
        tb.add(self._builder.gen_sub(tmp4, tmp5, tmp6))

        # Move bit 4 to AF flag.
        tb.add(self._builder.gen_bsh(tmp6, immn4, af))

    def _update_pf(self, tb, oprnd0, oprnd1, result):
        tmp0 = tb.temporal(result.size)
        tmp1 = tb.temporal(result.size)
        tmp2 = tb.temporal(result.size)
        tmp3 = tb.temporal(result.size)
        tmp4 = tb.temporal(result.size)
        tmp5 = tb.temporal(result.size)

        imm1 = tb.immediate(1, result.size)
        immn1 = tb.immediate(-1, result.size)
        immn2 = tb.immediate(-2, result.size)
        immn4 = tb.immediate(-4, result.size)

        pf = self._flags["pf"]

        # tmp1 =  result ^ (result >> 4)
        tb.add(self._builder.gen_bsh(result, immn4, tmp0))
        tb.add(self._builder.gen_xor(result, tmp0, tmp1))

        # tmp3 =  tmp1 ^ (tmp1 >> 2)
        tb.add(self._builder.gen_bsh(tmp1, immn2, tmp2))
        tb.add(self._builder.gen_xor(tmp2, tmp1, tmp3))

        # tmp5 = tmp3 ^ (tmp3 >> 1)
        tb.add(self._builder.gen_bsh(tmp3, immn1, tmp4))
        tb.add(self._builder.gen_xor(tmp4, tmp3, tmp5))

        # Invert and save result.
        tb.add(self._builder.gen_xor(tmp5, imm1, pf))

    def _update_sf(self, tb, oprnd0, oprnd1, result):
        # Create temporal variables.
        tmp0 = tb.temporal(result.size)

        mask0 = tb.immediate(2**(oprnd0.size - 1), result.size)
        shift0 = tb.immediate(-(oprnd0.size - 1), result.size)

        sf = self._flags["sf"]

        tb.add(self._builder.gen_and(result, mask0, tmp0))  # filter sign bit
        tb.add(self._builder.gen_bsh(tmp0, shift0, sf))  # extract sign bit

    def _update_of(self, tb, oprnd0, oprnd1, result):
        assert oprnd0.size == oprnd1.size

        of = self._flags["of"]

        imm0 = tb.immediate(1, 1)

        tmp0 = tb.temporal(1)
        tmp1 = tb.temporal(1)
        tmp2 = tb.temporal(1)
        tmp3 = tb.temporal(1)

        # Extract sign bit.
        oprnd0_sign = self._extract_sign_bit(tb, oprnd0)
        oprnd1_sign = self._extract_sign_bit(tb, oprnd1)
        result_sign = self._extract_bit(tb, result, oprnd0.size - 1)

        # Compute OF.
        tb.add(
            self._builder.gen_xor(oprnd0_sign, oprnd1_sign,
                                  tmp0))  # (sign bit oprnd0 ^ sign bit oprnd1)
        tb.add(self._builder.gen_xor(
            tmp0, imm0, tmp1))  # (sign bit oprnd0 ^ sign bit oprnd1 ^ 1)
        tb.add(
            self._builder.gen_xor(oprnd0_sign, result_sign,
                                  tmp2))  # (sign bit oprnd0 ^ sign bit result)
        tb.add(
            self._builder.gen_and(tmp1, tmp2, tmp3)
        )  # (sign bit oprnd0 ^ sign bit oprnd1 ^ 1) & (sign bit oprnd0 ^ sign bit result)

        # Save result.
        tb.add(self._builder.gen_str(tmp3, of))

    def _update_of_sub(self, tb, oprnd0, oprnd1, result):
        assert oprnd0.size == oprnd1.size

        of = self._flags["of"]

        imm0 = tb.immediate(1, 1)

        tmp0 = tb.temporal(1)
        tmp1 = tb.temporal(1)
        tmp2 = tb.temporal(1)
        tmp3 = tb.temporal(1)

        oprnd1_sign = tb.temporal(1)

        # Extract sign bit.
        oprnd0_sign = self._extract_sign_bit(tb, oprnd0)
        oprnd1_sign_tmp = self._extract_sign_bit(tb, oprnd1)
        result_sign = self._extract_bit(tb, result, oprnd0.size - 1)

        # Invert sign bit of oprnd2.
        tb.add(self._builder.gen_xor(oprnd1_sign_tmp, imm0, oprnd1_sign))

        # Compute OF.
        tb.add(
            self._builder.gen_xor(oprnd0_sign, oprnd1_sign,
                                  tmp0))  # (sign bit oprnd0 ^ sign bit oprnd1)
        tb.add(self._builder.gen_xor(
            tmp0, imm0, tmp1))  # (sign bit oprnd0 ^ sign bit oprnd1 ^ 1)
        tb.add(
            self._builder.gen_xor(oprnd0_sign, result_sign,
                                  tmp2))  # (sign bit oprnd0 ^ sign bit result)
        tb.add(
            self._builder.gen_and(tmp1, tmp2, tmp3)
        )  # (sign bit oprnd0 ^ sign bit oprnd1 ^ 1) & (sign bit oprnd0 ^ sign bit result)

        # Save result.
        tb.add(self._builder.gen_str(tmp3, of))

    def _update_cf(self, tb, oprnd0, oprnd1, result):
        cf = self._flags["cf"]

        imm0 = tb.immediate(2**oprnd0.size, result.size)
        imm1 = tb.immediate(-oprnd0.size, result.size)

        tmp0 = tb.temporal(result.size)

        tb.add(self._builder.gen_and(result, imm0, tmp0))  # filter carry bit
        tb.add(self._builder.gen_bsh(tmp0, imm1, cf))

    def _update_zf(self, tb, oprnd0, oprnd1, result):
        zf = self._flags["zf"]

        imm0 = tb.immediate((2**oprnd0.size) - 1, result.size)

        tmp0 = tb.temporal(oprnd0.size)

        tb.add(self._builder.gen_and(result, imm0,
                                     tmp0))  # filter low part of result
        tb.add(self._builder.gen_bisz(tmp0, zf))

    def _undefine_flag(self, tb, flag):
        # NOTE: In every test I've made, each time a flag is leave
        # undefined it is always set to 0.

        imm = tb.immediate(0, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    def _clear_flag(self, tb, flag):
        imm = tb.immediate(0, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    def _set_flag(self, tb, flag):
        imm = tb.immediate(1, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    # Helpers.
    # ======================================================================== #
    def _evaluate_a(self, tb):
        # above (CF=0 and ZF=0).
        return tb._and_regs(tb._negate_reg(self._flags["cf"]),
                            tb._negate_reg(self._flags["zf"]))

    def _evaluate_ae(self, tb):
        # above or equal (CF=0)
        return tb._negate_reg(self._flags["cf"])

    def _evaluate_b(self, tb):
        # below (CF=1)
        return self._flags["cf"]

    def _evaluate_be(self, tb):
        # below or equal (CF=1 or ZF=1)
        return tb._or_regs(self._flags["cf"], self._flags["zf"])

    def _evaluate_c(self, tb):
        # carry (CF=1)
        return self._flags["cf"]

    def _evaluate_e(self, tb):
        # equal (ZF=1)
        return self._flags["zf"]

    def _evaluate_g(self, tb):
        # greater (ZF=0 and SF=OF)
        return tb._and_regs(
            tb._negate_reg(self._flags["zf"]),
            tb._equal_regs(self._flags["sf"], self._flags["of"]))

    def _evaluate_ge(self, tb):
        # greater or equal (SF=OF)
        return tb._equal_regs(self._flags["sf"], self._flags["of"])

    def _evaluate_l(self, tb):
        # less (SF != OF)
        return tb._unequal_regs(self._flags["sf"], self._flags["of"])

    def _evaluate_le(self, tb):
        # less or equal (ZF=1 or SF != OF)
        return tb._or_regs(
            self._flags["zf"],
            tb._unequal_regs(self._flags["sf"], self._flags["of"]))

    def _evaluate_na(self, tb):
        # not above (CF=1 or ZF=1).
        return tb._or_regs(self._flags["cf"], self._flags["zf"])

    def _evaluate_nae(self, tb):
        # not above or equal (CF=1)
        return self._flags["cf"]

    def _evaluate_nb(self, tb):
        # not below (CF=0)
        return tb._negate_reg(self._flags["cf"])

    def _evaluate_nbe(self, tb):
        # not below or equal (CF=0 and ZF=0)
        return tb._and_regs(tb._negate_reg(self._flags["cf"]),
                            tb._negate_reg(self._flags["zf"]))

    def _evaluate_nc(self, tb):
        # not carry (CF=0)
        return tb._negate_reg(self._flags["cf"])

    def _evaluate_ne(self, tb):
        # not equal (ZF=0)
        return tb._negate_reg(self._flags["zf"])

    def _evaluate_ng(self, tb):
        # not greater (ZF=1 or SF != OF)
        return tb._or_regs(
            self._flags["zf"],
            tb._unequal_regs(self._flags["sf"], self._flags["of"]))

    def _evaluate_nge(self, tb):
        # not greater or equal (SF != OF)
        return tb._unequal_regs(self._flags["sf"], self._flags["of"])

    def _evaluate_nl(self, tb):
        # not less (SF=OF)
        return tb._equal_regs(self._flags["sf"], self._flags["of"])

    def _evaluate_nle(self, tb):
        # not less or equal (ZF=0 and SF=OF)
        return tb._and_regs(
            tb._negate_reg(self._flags["zf"]),
            tb._equal_regs(self._flags["sf"], self._flags["of"]))

    def _evaluate_no(self, tb):
        # not overflow (OF=0)
        return tb._negate_reg(self._flags["of"])

    def _evaluate_np(self, tb):
        # not parity (PF=0)
        return tb._negate_reg(self._flags["pf"])

    def _evaluate_ns(self, tb):
        # not sign (SF=0)
        return tb._negate_reg(self._flags["sf"])

    def _evaluate_nz(self, tb):
        # not zero (ZF=0)
        return tb._negate_reg(self._flags["zf"])

    def _evaluate_o(self, tb):
        # overflow (OF=1)
        return self._flags["of"]

    def _evaluate_p(self, tb):
        # parity (PF=1)
        return self._flags["pf"]

    def _evaluate_pe(self, tb):
        # parity even (PF=1)
        return self._flags["pf"]

    def _evaluate_po(self, tb):
        # parity odd (PF=0)
        return tb._negate_reg(self._flags["pf"])

    def _evaluate_s(self, tb):
        # sign (SF=1)
        return self._flags["sf"]

    def _evaluate_z(self, tb):
        # zero (ZF=1)
        return self._flags["zf"]

    # Helpers.
    # ======================================================================== #
    def _extract_bit(self, tb, reg, bit):
        assert (0 <= bit < reg.size)

        tmp = tb.temporal(reg.size)
        ret = tb.temporal(1)

        tb.add(self._builder.gen_bsh(reg, tb.immediate(-bit, reg.size),
                                     tmp))  # shift to LSB
        tb.add(self._builder.gen_and(tmp, tb.immediate(1, reg.size),
                                     ret))  # filter LSB

        return ret

    def _extract_msb(self, tb, reg):
        return self._extract_bit(tb, reg, reg.size - 1)

    def _extract_sign_bit(self, tb, reg):
        return self._extract_msb(tb, reg)
예제 #2
0
class ArmTranslator(InstructionTranslator):
    """ARM to IR Translator."""
    def __init__(self, architecture_mode=ARCH_ARM_MODE_THUMB):
        super(ArmTranslator, self).__init__()

        # Set *Architecture Mode*. The translation of each instruction
        # into the REIL language is based on this.
        self._arch_mode = architecture_mode

        # An instance of *ArchitectureInformation*.
        self._arch_info = ArmArchitectureInformation(architecture_mode)

        self._builder = ReilBuilder()

        self._flags = {
            "nf": ReilRegisterOperand("nf", 1),
            "zf": ReilRegisterOperand("zf", 1),
            "cf": ReilRegisterOperand("cf", 1),
            "vf": ReilRegisterOperand("vf", 1),
        }

        if self._arch_mode in [ARCH_ARM_MODE_ARM, ARCH_ARM_MODE_THUMB]:
            self._sp = ReilRegisterOperand("r13", 32)  # TODO: Implement alias
            self._pc = ReilRegisterOperand("r15", 32)
            self._lr = ReilRegisterOperand("r14", 32)

            self._ws = ReilImmediateOperand(4, 32)  # word size

    def translate(self, instruction):
        """Return IR representation of an instruction.
        """
        try:
            trans_instrs = self.__translate(instruction)
        except NotImplementedError:
            unkn_instr = self._builder.gen_unkn()
            unkn_instr.address = instruction.address << 8 | (0x0 & 0xff)
            trans_instrs = [unkn_instr]

            self._log_not_supported_instruction(instruction)
        except Exception:
            self._log_translation_exception(instruction)

            raise

        return trans_instrs

    def __translate(self, instruction):
        # Retrieve translation function.
        mnemonic = instruction.mnemonic

        tb = ArmTranslationBuilder(self._ir_name_generator, self._arch_mode)

        # TODO: Improve this.
        if instruction.mnemonic in [
                "b", "bl", "bx", "blx", "bne", "beq", "bpl", "ble", "bcs",
                "bhs", "blt", "bge", "bhi", "blo", "bls"
        ]:
            if instruction.condition_code is None:
                instruction.condition_code = ARM_COND_CODE_AL  # TODO: unify translations
        else:
            # Pre-processing: evaluate flags
            if instruction.condition_code is not None:
                self._evaluate_condition_code(tb, instruction)

        # Translate instruction.
        if mnemonic in translators.dispatcher:
            translators.dispatcher[mnemonic](self, tb, instruction)
        else:
            tb.add(self._builder.gen_unkn())

            self._log_not_supported_instruction(instruction)

        return tb.instanciate(instruction.address)

    # Flag translation.
    # ======================================================================== #
    def _update_nf(self, tb, oprnd0, oprnd1, result):
        sign = tb._extract_bit(result, oprnd0.size - 1)
        tb.add(self._builder.gen_str(sign, self._flags["nf"]))

    def _carry_from_uf(self, tb, oprnd0, oprnd1, result):
        assert (result.size == oprnd0.size * 2)

        carry = tb._extract_bit(result, oprnd0.size)
        tb.add(self._builder.gen_str(carry, self._flags["cf"]))

    def _borrow_from_uf(self, tb, oprnd0, oprnd1, result):
        # BorrowFrom as defined in the ARM Reference Manual has the same implementation as CarryFrom
        self._carry_from_uf(tb, oprnd0, oprnd1, result)

    def _overflow_from_add_uf(self, tb, oprnd0, oprnd1, result):
        op1_sign = tb._extract_bit(oprnd0, oprnd0.size - 1)
        op2_sign = tb._extract_bit(oprnd1, oprnd0.size - 1)
        res_sign = tb._extract_bit(result, oprnd0.size - 1)

        overflow = tb._and_regs(tb._equal_regs(op1_sign, op2_sign),
                                tb._unequal_regs(op1_sign, res_sign))
        tb.add(self._builder.gen_str(overflow, self._flags["vf"]))

    def _overflow_from_sub_uf(self, tb, oprnd0, oprnd1, result):
        # Evaluate overflow and update the flag
        tb.add(
            self._builder.gen_str(
                tb._overflow_from_sub(oprnd0, oprnd1, result),
                self._flags["vf"]))

    def _update_zf(self, tb, oprnd0, oprnd1, result):
        zf = self._flags["zf"]

        imm0 = tb.immediate((2**oprnd0.size) - 1, result.size)

        tmp0 = tb.temporal(oprnd0.size)

        tb.add(self._builder.gen_and(result, imm0,
                                     tmp0))  # filter low part of result
        tb.add(self._builder.gen_bisz(tmp0, zf))

    def _carry_out(self, tb, carry_operand, oprnd0, oprnd1, result):
        if isinstance(carry_operand, ArmImmediateOperand):
            return
        elif isinstance(carry_operand, ArmRegisterOperand):
            return
        elif isinstance(carry_operand, ArmShiftedRegisterOperand):
            base = ReilRegisterOperand(carry_operand.base_reg.name,
                                       carry_operand.size)
            shift_type = carry_operand.shift_type
            shift_amount = carry_operand.shift_amount

            if shift_type == 'lsl':

                if isinstance(shift_amount, ArmImmediateOperand):
                    if shift_amount.immediate == 0:
                        return
                    else:
                        # carry_out = Rm[32 - shift_imm]
                        shift_carry_out = tb._extract_bit(
                            base, 32 - shift_amount.immediate)

                elif isinstance(shift_amount, ArmRegisterOperand):
                    # Rs: register with shift amount
                    # if Rs[7:0] == 0 then
                    #     carry_out = C Flag
                    # else if Rs[7:0] <= 32 then
                    #     carry_out = Rm[32 - Rs[7:0]]
                    # else /* Rs[7:0] > 32 */
                    #     carry_out = 0

                    shift_carry_out = tb.temporal(1)
                    tb.add(
                        self._builder.gen_str(self._flags["cf"],
                                              shift_carry_out))
                    rs = ReilRegisterOperand(shift_amount.name,
                                             shift_amount.size)
                    rs_7_0 = tb._and_regs(rs, tb.immediate(0xFF, rs.size))

                    end_label = tb.label('end_label')
                    rs_greater_32_label = tb.label('rs_greater_32_label')

                    # if Rs[7:0] == 0 then
                    #     carry_out = C Flag
                    tb._jump_if_zero(
                        rs_7_0, end_label
                    )  # shift_carry_out already has the C flag set, so do nothing

                    tb.add(
                        self._builder.gen_jcc(
                            tb._greater_than_or_equal(
                                rs_7_0, tb.immediate(33, rs_7_0.size)),
                            rs_greater_32_label))

                    # Rs > 0 and Rs <= 32
                    #     carry_out = Rm[32 - Rs[7:0]]
                    extract_bit_number = tb.temporal(rs_7_0.size)
                    tb.add(
                        self._builder.gen_sub(tb.immediate(32, rs_7_0.size),
                                              rs_7_0, extract_bit_number))
                    tb.add(
                        self._builder.gen_str(
                            tb._extract_bit_with_register(
                                base, extract_bit_number), shift_carry_out))
                    tb._jump_to(end_label)

                    # else /* Rs[7:0] > 32 */
                    #     carry_out = 0
                    tb.add(rs_greater_32_label)
                    tb.add(
                        self._builder.gen_str(tb.immediate(0, 1),
                                              shift_carry_out))
                    # tb._jump_to(end_label)

                    tb.add(end_label)

                else:
                    raise Exception("carry_out: Unknown shift amount type.")

            else:
                # TODO: Implement other shift types
                raise NotImplementedError(
                    "Instruction Not Implemented: carry_out: shift type " +
                    carry_operand.shift_type)

        else:
            raise Exception("carry_out: Unknown operand type.")

        tb.add(self._builder.gen_str(shift_carry_out, self._flags["cf"]))

    def _update_flags_data_proc_add(self, tb, oprnd0, oprnd1, result):
        self._update_zf(tb, oprnd0, oprnd1, result)
        self._update_nf(tb, oprnd0, oprnd1, result)
        self._carry_from_uf(tb, oprnd0, oprnd1, result)
        self._overflow_from_add_uf(tb, oprnd0, oprnd1, result)

    def _update_flags_data_proc_sub(self, tb, oprnd0, oprnd1, result):
        self._update_zf(tb, oprnd0, oprnd1, result)
        self._update_nf(tb, oprnd0, oprnd1, result)
        self._borrow_from_uf(tb, oprnd0, oprnd1, result)
        # C Flag = NOT BorrowFrom (to be used by subsequent instructions like SBC and RSC)
        tb.add(
            self._builder.gen_str(tb._negate_reg(self._flags["cf"]),
                                  self._flags["cf"]))
        self._overflow_from_sub_uf(tb, oprnd0, oprnd1, result)

    def _update_flags_data_proc_other(self, tb, second_operand, oprnd0, oprnd1,
                                      result):
        self._update_zf(tb, oprnd0, oprnd1, result)
        self._update_nf(tb, oprnd0, oprnd1, result)
        self._carry_out(tb, second_operand, oprnd0, oprnd1, result)
        # Overflow Flag (V) unaffected

    def _update_flags_other(self, tb, oprnd0, oprnd1, result):
        self._update_zf(tb, oprnd0, oprnd1, result)
        self._update_nf(tb, oprnd0, oprnd1, result)
        # Carry Flag (C) unaffected
        # Overflow Flag (V) unaffected

    def _undefine_flag(self, tb, flag):
        # NOTE: In every test I've made, each time a flag is leave
        # undefined it is always set to 0.

        imm = tb.immediate(0, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    def _clear_flag(self, tb, flag):
        imm = tb.immediate(0, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    def _set_flag(self, tb, flag):
        imm = tb.immediate(1, flag.size)

        tb.add(self._builder.gen_str(imm, flag))

    # Helpers.
    # ======================================================================== #
    def _evaluate_eq(self, tb):
        # EQ: Z set
        return self._flags["zf"]

    def _evaluate_ne(self, tb):
        # NE: Z clear
        return tb._negate_reg(self._flags["zf"])

    def _evaluate_cs(self, tb):
        # CS: C set
        return self._flags["cf"]

    def _evaluate_cc(self, tb):
        # CC: C clear
        return tb._negate_reg(self._flags["cf"])

    def _evaluate_mi(self, tb):
        # MI: N set
        return self._flags["nf"]

    def _evaluate_pl(self, tb):
        # PL: N clear
        return tb._negate_reg(self._flags["nf"])

    def _evaluate_vs(self, tb):
        # VS: V set
        return self._flags["vf"]

    def _evaluate_vc(self, tb):
        # VC: V clear
        return tb._negate_reg(self._flags["vf"])

    def _evaluate_hi(self, tb):
        # HI: C set and Z clear
        return tb._and_regs(self._flags["cf"],
                            tb._negate_reg(self._flags["zf"]))

    def _evaluate_ls(self, tb):
        # LS: C clear or Z set
        return tb._or_regs(tb._negate_reg(self._flags["cf"]),
                           self._flags["zf"])

    def _evaluate_ge(self, tb):
        # GE: N == V
        return tb._equal_regs(self._flags["nf"], self._flags["vf"])

    def _evaluate_lt(self, tb):
        # LT: N != V
        return tb._negate_reg(self._evaluate_ge(tb))

    def _evaluate_gt(self, tb):
        # GT: (Z == 0) and (N == V)
        return tb._and_regs(tb._negate_reg(self._flags["zf"]),
                            self._evaluate_ge(tb))

    def _evaluate_le(self, tb):
        # LE: (Z == 1) or (N != V)
        return tb._or_regs(self._flags["zf"], self._evaluate_lt(tb))

    def _evaluate_condition_code(self, tb, instruction):
        if instruction.condition_code == ARM_COND_CODE_AL:
            return

        eval_cc_fn = {
            ARM_COND_CODE_EQ: self._evaluate_eq,
            ARM_COND_CODE_NE: self._evaluate_ne,
            ARM_COND_CODE_CS: self._evaluate_cs,
            ARM_COND_CODE_HS: self._evaluate_cs,
            ARM_COND_CODE_CC: self._evaluate_cc,
            ARM_COND_CODE_LO: self._evaluate_cc,
            ARM_COND_CODE_MI: self._evaluate_mi,
            ARM_COND_CODE_PL: self._evaluate_pl,
            ARM_COND_CODE_VS: self._evaluate_vs,
            ARM_COND_CODE_VC: self._evaluate_vc,
            ARM_COND_CODE_HI: self._evaluate_hi,
            ARM_COND_CODE_LS: self._evaluate_ls,
            ARM_COND_CODE_GE: self._evaluate_ge,
            ARM_COND_CODE_LT: self._evaluate_lt,
            ARM_COND_CODE_GT: self._evaluate_gt,
            ARM_COND_CODE_LE: self._evaluate_le,
        }

        neg_cond = tb._negate_reg(eval_cc_fn[instruction.condition_code](tb))

        end_addr = ReilImmediateOperand(
            (instruction.address + instruction.size) << 8,
            self._arch_info.address_size + 8)

        tb.add(self._builder.gen_jcc(neg_cond, end_addr))

        return
예제 #3
0
class TranslationBuilder(object):
    def __init__(self, ir_name_generator, architecture_information):
        self._ir_name_generator = ir_name_generator

        self._instructions = []

        self._builder = ReilBuilder()

        self._arch_info = architecture_information

    def add(self, instr):
        self._instructions.append(instr)

    def temporal(self, size):
        return ReilRegisterOperand(self._ir_name_generator.get_next(), size)

    def immediate(self, value, size):
        return ReilImmediateOperand(value, size)

    def label(self, name):
        return Label(name)

    def instanciate(self, address):
        # Set instructions address.
        instrs = self._instructions

        for instr in instrs:
            instr.address = address << 8

        instrs = self._resolve_loops(instrs)

        return instrs

    # Auxiliary functions
    # ======================================================================== #

    def _resolve_loops(self, instrs):
        idx_by_labels = {}

        # Collect labels.
        #         curr = 0
        #         for index, instr in enumerate(instrs):
        #             if isinstance(instr, Label):
        #                 idx_by_labels[instr.name] = curr
        #
        #                 del instrs[index]
        #             else:
        #                 curr += 1

        # TODO: Hack to avoid deleting while iterating
        instrs_no_labels = []
        curr = 0
        for i in instrs:
            if isinstance(i, Label):
                idx_by_labels[i.name] = curr
            else:
                instrs_no_labels.append(i)
                curr += 1

        instrs[:] = instrs_no_labels

        # Resolve instruction addresses and JCC targets.
        for index, instr in enumerate(instrs):
            assert isinstance(instr, ReilInstruction)

            instr.address |= index

            if instr.mnemonic == ReilMnemonic.JCC:
                target = instr.operands[2]

                if isinstance(target, Label):
                    idx = idx_by_labels[target.name]
                    address = (instr.address & ~0xff) | idx

                    instr.operands[2] = ReilImmediateOperand(
                        address, self._arch_info.address_size + 8)

        return instrs

    def _all_ones_imm(self, reg):
        return self.immediate((2**reg.size) - 1, reg.size)

    def _negate_reg(self, reg):
        neg = self.temporal(reg.size)
        self.add(self._builder.gen_xor(reg, self._all_ones_imm(reg), neg))
        return neg

    def _and_regs(self, reg1, reg2):
        ret = self.temporal(reg1.size)
        self.add(self._builder.gen_and(reg1, reg2, ret))
        return ret

    def _or_regs(self, reg1, reg2):
        ret = self.temporal(reg1.size)
        self.add(self._builder.gen_or(reg1, reg2, ret))
        return ret

    def _xor_regs(self, reg1, reg2):
        ret = self.temporal(reg1.size)
        self.add(self._builder.gen_xor(reg1, reg2, ret))
        return ret

    def _equal_regs(self, reg1, reg2):
        return self._negate_reg(self._xor_regs(reg1, reg2))

    def _unequal_regs(self, reg1, reg2):
        return self._xor_regs(reg1, reg2)

    def _shift_reg(self, reg, sh):
        ret = self.temporal(reg.size)
        self.add(self._builder.gen_bsh(reg, sh, ret))
        return ret

    def _extract_bit(self, reg, bit):
        assert (0 <= bit < reg.size)
        tmp = self.temporal(reg.size)
        ret = self.temporal(1)

        self.add(
            self._builder.gen_bsh(reg, self.immediate(-bit, reg.size),
                                  tmp))  # shift to LSB
        self.add(self._builder.gen_and(tmp, self.immediate(1, reg.size),
                                       ret))  # filter LSB

        return ret

    # Same as before but the bit number is indicated by a register and it will be resolved at runtime
    def _extract_bit_with_register(self, reg, bit):
        # assert(bit >= 0 and bit < reg.size2) # It is assumed, it is not checked
        tmp = self.temporal(reg.size)
        neg_bit = self.temporal(reg.size)
        ret = self.temporal(1)

        self.add(
            self._builder.gen_sub(
                self.immediate(0, bit.size), bit,
                neg_bit))  # as left bit is indicated by a negative number
        self.add(self._builder.gen_bsh(reg, neg_bit, tmp))  # shift to LSB
        self.add(self._builder.gen_and(tmp, self.immediate(1, reg.size),
                                       ret))  # filter LSB

        return ret

    def _extract_msb(self, reg):
        return self._extract_bit(reg, reg.size - 1)

    def _extract_sign_bit(self, reg):
        return self._extract_msb(reg)

    def _greater_than_or_equal(self, reg1, reg2):
        assert (reg1.size == reg2.size)
        result = self.temporal(reg1.size * 2)

        self.add(self._builder.gen_sub(reg1, reg2, result))

        sign = self._extract_bit(result, reg1.size - 1)
        overflow = self._overflow_from_sub(reg1, reg2, result)

        return self._equal_regs(sign, overflow)

    def _jump_to(self, target):
        self.add(self._builder.gen_jcc(self.immediate(1, 1), target))

    def _jump_if_zero(self, reg, label):
        is_zero = self.temporal(1)
        self.add(self._builder.gen_bisz(reg, is_zero))
        self.add(self._builder.gen_jcc(is_zero, label))

    def _add_to_reg(self, reg, value):
        res = self.temporal(reg.size)
        self.add(self._builder.gen_add(reg, value, res))

        return res

    def _sub_to_reg(self, reg, value):
        res = self.temporal(reg.size)
        self.add(self._builder.gen_sub(reg, value, res))

        return res

    def _overflow_from_sub(self, oprnd0, oprnd1, result):
        op1_sign = self._extract_bit(oprnd0, oprnd0.size - 1)
        op2_sign = self._extract_bit(oprnd1, oprnd0.size - 1)
        res_sign = self._extract_bit(result, oprnd0.size - 1)

        return self._and_regs(self._unequal_regs(op1_sign, op2_sign),
                              self._unequal_regs(op1_sign, res_sign))