Exemplo n.º 1
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        address = InstructionAddress(
            base_address="code",
            displacement=building_block.context.code_segment - self._address
        )

        for instr in building_block.init:
            instr.set_address(address.copy())
            return []

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:
                instr.set_address(address.copy())
                return []

        for instr in building_block.fini:
            instr.set_address(address.copy())
            return []

        return []
Exemplo n.º 2
0
 def branch_to_itself(self):
     instr = self.branch_unconditional_relative(
         InstructionAddress(
             base_address="code"
         ),
         InstructionAddress(
             base_address="code"
         )
     )
     instr.set_address(None)
     return instr
Exemplo n.º 3
0
def _compute_reset_jump(target, num_ins):
    source_instruction = InstructionAddress(
        base_address="code", displacement=0,
    )
    target_instruction = InstructionAddress(
        base_address="code", displacement=num_ins * (-4),
    )
    return [
        target.branch_unconditional_relative(
            source_instruction, target_instruction,
        ),
    ]
Exemplo n.º 4
0
    def end_loop(self, instr):
        """

        :param instr:

        """

        padding = 0
        instrs = []
        for dummy in range(0, self._dithering):
            instrs.append(self.target.nop())
            padding += self.target.nop().architecture_type.format.length

        source = InstructionAddress(
            base_address="code",
            displacement=instr.address.displacement + padding +
            instr.architecture_type.format.length
        )

        if self._endless:
            branch = self.target.branch_unconditional_relative(
                source, self._start_address
            )
            instrs.append(branch)

        end = [self.wrap_ins(elem) for elem in instrs]

        if len(end) == 0:
            return []

        endall = end[0]
        for elem in end[1:]:
            endall += elem
        return endall
Exemplo n.º 5
0
    def check(self, building_block, dummy_target):
        """

        :param building_block:
        :param dummy_target:

        """

        pass_ok = True
        for bbl in building_block.cfg.bbls:
            instr_ant = None

            for instr in bbl.instrs:

                if instr_ant is None:
                    instr_ant = instr
                    continue

                if not instr_ant.branch:
                    instr_ant = instr
                    continue

                pass_ok = pass_ok and instr.label != ""

                for memoperand in instr_ant.memory_operands():

                    if not memoperand.descriptor.is_branch_target:
                        continue

                    taddress = InstructionAddress(base_address=instr.label)
                    pass_ok = pass_ok and memoperand.address == taddress

                instr_ant = instr

        return pass_ok
Exemplo n.º 6
0
    def check(self, building_block, dummy_target):
        """

        :param building_block:
        :param dummy_target:

        """

        pass_ok = True
        caddress = InstructionAddress(base_address="code", displacement=0)

        for instr in building_block.init:
            pass_ok = pass_ok and caddress == instr.address
            caddress += instr.architecture_type.format.length

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:
                pass_ok = pass_ok and caddress == instr.address
                caddress += instr.architecture_type.format.length

        for instr in building_block.fini:
            pass_ok = pass_ok and caddress == instr.address
            caddress += instr.architecture_type.format.length

        # daddress = Address(base_address="data",
        #                   displacement=0)

        # for variable in building_block.registered_global_vars():
        #    daddress += variable.get_displacement()
        #    pass_ok = variable.address == daddress

        return pass_ok
Exemplo n.º 7
0
def _compute_reset_jump(target, instrs):
    source_instruction = InstructionAddress(
        base_address="code", displacement=0,
    )

    displacement = 0
    for instr in instrs:
        displacement = displacement - instr.architecture_type.format.length

    target_instruction = InstructionAddress(
        base_address="code", displacement=displacement,
    )
    return [
        target.branch_unconditional_relative(
            source_instruction, target_instruction,
        ),
    ]
Exemplo n.º 8
0
def _extract_address(address):
    """

    :param address:
    :type address:
    """
    if address is not None:
        return InstructionAddress(base_address="code", displacement=address)
    return address
Exemplo n.º 9
0
    def function_call(self, target, return_address_reg=None, long_jump=False):

        if return_address_reg is None:
            return_address_reg = self.target.isa.registers["X1"]

        if isinstance(target, str):
            target = InstructionAddress(base_address=target)

        jal_ins = self.target.new_instruction("JAL_V0")
        jal_ins.set_operands([target, return_address_reg])

        return [jal_ins]
Exemplo n.º 10
0
    def __call__(self, building_block, dummy_target):

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:
                building_block.context.dat.update_dat(**instr.decorators)

                address = instr.address.copy()
                if address.base_address == "code":
                    raw_address = building_block.context.code_segment +\
                        address.displacement
                else:
                    raise NotImplementedError

                trans_address = building_block.context.dat.translate(
                    raw_address)
                new_address = InstructionAddress(base_address="abs",
                                                 displacement=trans_address)
                instr.set_address(new_address)
Exemplo n.º 11
0
    def compare_and_branch(self, val1, val2, cond, target, context):

        assert cond in ["<", ">", "!=", "=", ">=", "<="]
        instrs = []

        # put all values into registers
        if isinstance(val1, int) and isinstance(val1, six.integer_types):
            raise NotImplementedError
        elif isinstance(val1, six.integer_types):
            instrs += self.set_register(
                self.scratch_registers[0], val1, context
            )
            val1 = self.scratch_registers[0]
        elif isinstance(val2, six.integer_types):
            instrs += self.set_register(
                self.scratch_registers[0], val2, context
            )
            val2 = self.scratch_registers[0]

        if isinstance(target, str):
            target = InstructionAddress(base_address=target)

        if cond == ">":
            cond = "<"
            val1, val2 = val2, val1
        if cond == "<=":
            cond = ">="
            val1, val2 = val2, val1

        if cond == "=":
            bc_ins = self.new_instruction("BEQ_V0")
        elif cond == "!=":
            bc_ins = self.new_instruction("BNE_V0")
        elif cond == "<":
            bc_ins = self.new_instruction("BLT_V0")
        elif cond == ">=":
            bc_ins = self.new_instruction("BGE_V0")
        else:
            raise NotImplementedError

        bc_ins.set_operands([target, val2, val1, 0])
        instrs.append(bc_ins)
        return instrs
Exemplo n.º 12
0
    def function_call(self, target, return_address_reg=None, long_jump=False):

        if return_address_reg is None:
            return_address_reg = self.target.isa.registers["X1"]

        if isinstance(target, str):
            target = InstructionAddress(base_address=target)

        if long_jump:
            assert isinstance(target, int)
            instrs = self.target.set_register(return_address_reg, target,
                                              Context())

            jalr_ins = self.target.new_instruction("JALR_V0")
            jalr_ins.set_operands([0, return_address_reg, return_address_reg])
            jalr_ins.add_comment("Long jump to address 0X%016X" % target)

            instrs.append(jalr_ins)
            return instrs

        else:
            jal_ins = self.target.new_instruction("JAL_V0")
            jal_ins.set_operands([target, return_address_reg])
            return [jal_ins]
Exemplo n.º 13
0
    def check(self, building_block, dummy_target):
        """

        :param building_block:
        :param dummy_target:

        """

        address = InstructionAddress(
            base_address="code",
            displacement=building_block.context.code_segment - self._address
        )

        for instr in building_block.init:
            return instr.address == address

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:
                return instr.address == address

        for instr in building_block.fini:
            return instr.address == address

        return False
Exemplo n.º 14
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """
        def fill_block(block, function):

            for instr in block.instrs:
                instr.set_arch_type(function())

                context_fix_functions = instr.check_context(
                    building_block.context)

                for context_fix_function in context_fix_functions:
                    try:
                        context_fix_function(target, building_block)
                    except MicroprobeUncheckableEnvironmentWarning as \
                            warning_check:
                        building_block.add_warning(str(warning_check))

        controlreg = target.get_register_for_address_arithmetic(
            building_block.context)

        for idx, sequence in enumerate(self._sequences):

            next_instruction, block_size, block_iterations, extra = sequence

            if block_iterations > 1:

                init_loop = target.set_register(controlreg, block_iterations,
                                                building_block.context)

                if controlreg not in building_block.context.reserved_registers:
                    building_block.context.add_reserved_registers([controlreg])

                init_bbl = building_block.cfg.add_bbl(instructions=init_loop)

                for instr in init_bbl.instrs:
                    instr.add_allow_register(controlreg)

            block_bbl = building_block.cfg.add_bbl(size=block_size)
            fill_block(block_bbl, next_instruction)

            if block_iterations > 1:

                label = "sequence_%d" % idx
                block_bbl.instrs[0].set_label(label)
                add_cmp_branch = target.add_to_register(controlreg, -1)

                for instr in add_cmp_branch:
                    instr.add_allow_register(controlreg)

                add_cmp_branch += target.compare_and_branch(
                    controlreg, 0, ">", InstructionAddress(base_address=label),
                    building_block.context)

                block_bbl.insert_instr(add_cmp_branch,
                                       after=block_bbl.instrs[-1])

            if extra > 0:

                extra_bbl = building_block.cfg.add_bbl(size=(extra))
                fill_block(extra_bbl, next_instruction)

        return []
Exemplo n.º 15
0
    def __call__(self, building_block, dummy_target):

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:

                if not (instr.branch or instr.trap):
                    continue

                if "BP" not in instr.decorators and instr.branch_conditional:
                    instr.add_decorator("BP", self._default)
                elif "BP" not in instr.decorators:
                    instr.add_decorator("BP", "T")

                pattern = instr.decorators["BP"]["value"]

                target_addr = None
                for memoper in instr.memory_operands():
                    if isinstance(memoper.address, InstructionAddress):
                        target_addr = memoper.address
                        break

                if target_addr is None:
                    for oper in instr.operands():
                        if isinstance(oper.value, InstructionAddress):
                            target_addr = oper.value
                            break

                if target_addr is None:
                    if "BT" in instr.decorators:
                        target_addr = instr.decorators["BT"]['value']
                    else:
                        target_addr = self._indirect
                else:
                    if "BT" in instr.decorators:
                        bt_addr = [
                            int(elem, 16)
                            for elem in instr.decorators["BT"]['value']
                        ]

                        if building_block.context.code_segment is not None:
                            bt_addr = [
                                elem - building_block.context.code_segment
                                for elem in bt_addr
                            ]

                        if instr.branch_conditional:
                            bt_addr = [
                                elem for elem in bt_addr
                                if elem != instr.address.displacement +
                                instr.architecture_type.format.length
                            ]

                        if len(set(bt_addr)) != 1:
                            raise MicroprobeCodeGenerationError(
                                "BT decorator with multiple targets "
                                "defined but instruction '%s' already"
                                " defines the target in its codification." %
                                (instr.assembly()))

                        bt_addr = bt_addr[0]
                        if bt_addr != target_addr.displacement:

                            raise MicroprobeCodeGenerationError(
                                "BT decorator specified for instruction '%s' "
                                "but it already provides the target in its "
                                "codification and they miss-match!" %
                                (instr.assembly()))
                        instr.decorators.pop("BT")

                if not instr.branch_conditional and 'N' in pattern:
                    raise MicroprobeCodeGenerationError(
                        "Not take branch pattern provided for an "
                        "unconditional branch '%s'" % instr.assembly())

                if pattern is None:

                    def function_pattern():
                        raise MicroprobeCodeGenerationError(
                            "No branch pattern provided for branch '%s'" %
                            instr.assembly())

                    pattern_error = self._error_class(function_pattern)
                    instr.add_decorator("NI", pattern_error)
                    continue

                if target_addr is None:

                    def function_target_addr():
                        raise MicroprobeCodeGenerationError(
                            "No target address provided for branch '%s'" %
                            instr.assembly())

                    target_addr_error = self._error_class(function_target_addr)
                    instr.add_decorator("NI", target_addr_error)
                    continue

                if not isinstance(target_addr, list):
                    target_addr = [target_addr]

                for idx, address in enumerate(target_addr):

                    if isinstance(address, str):
                        address = int(address, 16)

                    if not isinstance(address, InstructionAddress):

                        code = 0
                        if building_block.context.code_segment is not None:
                            code = building_block.context.code_segment

                        target_addr[idx] = InstructionAddress(
                            base_address="code", displacement=address - code)

                next_address = instr.address + \
                    instr.architecture_type.format.length

                def pattern_gen(lnext_address, lpattern, ltarget_addr):

                    target_iter = itertools.cycle(list(lpattern))
                    taken_target_address = itertools.cycle(ltarget_addr)

                    while True:
                        if next(target_iter) is 'N':
                            yield lnext_address
                        else:
                            yield next(taken_target_address)

                instr.add_decorator(
                    "NI",
                    itertools.cycle(
                        pattern_gen(next_address, pattern, target_addr)))
Exemplo n.º 16
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        if not building_block.context.register_has_value(0):
            reg = target.get_register_for_address_arithmetic(
                building_block.context)
            building_block.add_init(
                target.set_register(reg, 0, building_block.context))
            building_block.context.set_register_value(reg, 0)
            building_block.context.add_reserved_registers([reg])

        counter = 0
        all_counter = 0
        rregs = 0
        labels = []

        label_instruction_map = {}

        instr_ant = None

        for bbl in building_block.cfg.bbls:

            for instr in bbl.instrs:

                if instr_ant is None:
                    instr_ant = instr

                    if instr.label is None:
                        first_label = "first"
                        instr.set_label("first")
                        label_instruction_map[first_label] = instr
                    else:
                        first_label = instr.label
                        label_instruction_map[first_label] = instr

                    continue

                if not instr_ant.branch:
                    instr_ant = instr
                    continue

                if self._branch is not None and \
                        instr_ant.name != self._branch:
                    instr_ant = instr
                    continue

                LOG.debug("Setting target for branch: '%s'", instr_ant)
                target_set = False

                for memoperand in instr_ant.memory_operands():

                    if not memoperand.descriptor.is_branch_target:
                        continue

                    if memoperand.address is not None and not self._force:
                        continue

                    if target_set:
                        continue

                    LOG.debug("Computing label")

                    if instr_ant.branch_relative:

                        if instr.label is None:
                            label = "rel_branch_%d" % all_counter
                            instr.set_label(label)
                            LOG.debug("Branch relative, new label: '%s'",
                                      label)
                        else:
                            label = instr.label
                            LOG.debug("Branch relative, existing label: '%s'",
                                      label)

                    elif rregs < 5:

                        if instr.label is None:
                            label = "abs_branch_%d" % counter
                            labels.append(label)
                            instr.set_label(label)
                            LOG.debug("Branch absolute, new label: '%s'",
                                      label)
                        else:
                            label = instr.label
                            LOG.debug("Branch absolute, exiting label: '%s'",
                                      label)

                        label_instruction_map[label] = instr
                    else:
                        label = labels[counter % 5]

                    assert label is not None

                    taddress = InstructionAddress(base_address=label)

                    if instr_ant.branch_relative:
                        taddress.set_target_instruction(instr)
                    else:
                        taddress.set_target_instruction(
                            label_instruction_map[label])

                    try:
                        memoperand.set_address(taddress,
                                               building_block.context)
                        target_set = True
                        instr_ant.add_comment("Branch fixed to: %s" % taddress)

                    except MicroprobeCodeGenerationError:

                        reg = \
                            target.get_register_for_address_arithmetic(
                                building_block.context)
                        building_block.add_init(
                            target.set_register_to_address(
                                reg, taddress, building_block.context))
                        building_block.context.set_register_value(
                            reg, taddress)

                        building_block.context.add_reserved_registers([reg])

                        memoperand.set_address(taddress,
                                               building_block.context)

                        rregs += 1
                        target_set = True
                        instr_ant.add_comment("Branch fixed to: %s" % taddress)

                if not instr_ant.branch_relative:
                    counter += 1
                else:
                    all_counter += 1

                instr_ant = instr

        bbl = building_block.cfg.bbls[-1]
        if bbl.instrs[-1].branch:
            LOG.debug("Last instruction is a BRANCH: %s", bbl.instrs[-1])
            for memoperand in bbl.instrs[-1].memory_operands():

                if not memoperand.descriptor.is_branch_target:
                    continue

                if memoperand.address is not None and not self._force:
                    continue

                target_set = False
                for operand in memoperand.operands:
                    if operand.value is not None and not self._force:
                        target_set = True
                        break

                if target_set:
                    continue

                if (len(building_block.fini) > 0
                        and bbl.instrs[-1].branch_relative):

                    if building_block.fini[0].label is None:
                        label = "rel_branch_%d" % all_counter
                        building_block.fini[0].set_label(label)
                    else:
                        label = building_block.fini[0].label

                    taddress = InstructionAddress(base_address=label)
                    taddress.set_target_instruction(
                        label_instruction_map[first_label])
                else:
                    assert first_label is not None

                    taddress = InstructionAddress(base_address=first_label)
                    taddress.set_target_instruction(
                        label_instruction_map[first_label])

                try:
                    memoperand.set_address(taddress, building_block.context)
                except MicroprobeCodeGenerationError:

                    reg = \
                        target.get_register_for_address_arithmetic(
                            building_block.context)
                    building_block.add_init(
                        target.set_register_to_address(reg, taddress,
                                                       building_block.context))
                    building_block.context.set_register_value(reg, taddress)

                    building_block.context.add_reserved_registers([reg])

                    memoperand.set_address(taddress, building_block.context)
Exemplo n.º 17
0
    def compare_and_branch(self, val1, val2, cond, target, context):

        assert cond in ["<", ">", "!=", "=", ">=", "<="]

        instrs = []

        if isinstance(val1, Register) and isinstance(val2, six.integer_types):

            cmpi_ins = self.new_instruction("CMPI_V0")
            cmpi_ins.set_operands([self.scratch_registers[6], 1, val1, val2])
            for reg in cmpi_ins.sets() + cmpi_ins.uses():
                if reg not in cmpi_ins.allowed_regs:
                    cmpi_ins.add_allow_register(reg)
            instrs.append(cmpi_ins)

        elif isinstance(val1, Register) and isinstance(val2, Register):

            assert val1.type.name == val2.type.name

            if val1.type.name == "GPR":

                cmp_ins = self.new_instruction("CMP_V0")
                cmp_ins.set_operands(
                    [self.scratch_registers[6], 1, val1, val2])
                instrs.append(cmp_ins)

            elif val1.type.name == "FPR":

                fcmpu_ins = self.new_instruction("FCMPU_V0")
                fcmpu_ins.set_operands([self.scratch_registers[6], val1, val2])
                instrs.append(fcmpu_ins)

            else:

                raise NotImplementedError

        else:

            raise NotImplementedError

        # Fix to use BF 4 of the CR register (it is set in the
        # reserved list of registers
        cr_field = 4

        if cond == "<":

            bo_value = 12
            bi_value = (cr_field * 4) + 0

        elif cond == ">=":

            bo_value = 4
            bi_value = (cr_field * 4) + 0

        elif cond == ">":

            bo_value = 12
            bi_value = (cr_field * 4) + 1

        elif cond == "<=":

            bo_value = 4
            bi_value = (cr_field * 4) + 1

        elif cond == "=":

            bo_value = 12
            bi_value = (cr_field * 4) + 2

        elif cond == "!=":

            bo_value = 4
            bi_value = (cr_field * 4) + 2

        else:

            raise NotImplementedError

        bc_ins = self.new_instruction("BC_V0")
        bc_ins.operands()[0].set_value(bo_value)
        bc_ins.operands()[1].set_value(bi_value)

        for operand in bc_ins.memory_operands():

            if operand.is_branch_target:
                taddress = InstructionAddress(base_address=target)
                operand.set_address(taddress, context)
                break

        instrs.append(bc_ins)

        return instrs
Exemplo n.º 18
0
    def set_register_to_address(self,
                                register,
                                address,
                                context,
                                force_absolute=False,
                                force_relative=False):
        instrs = []

        assert address is not None

        LOG.debug("Begin setting '%s' to address '%s'", register, address)

        if isinstance(address.base_address, Variable):

            LOG.debug("Base address is a Variable: %s", address.base_address)
            closest = context.get_closest_address_value(address)

            if context.register_has_value(address):

                present_reg = context.registers_get_value(address)[0]
                displacement = 0
                LOG.debug("Address already in register '%s'", present_reg)

            elif closest is not None:

                present_reg, taddress = closest
                displacement = address.displacement - taddress.displacement
                LOG.debug("Closest value '%s' found in '%s'", taddress,
                          present_reg)
                LOG.debug("Displacement needed: %s", displacement)

            elif context.register_has_value(
                    Address(base_address=address.base_address)):

                present_reg = context.registers_get_value(
                    Address(base_address=address.base_address))[0]
                displacement = address.displacement
                LOG.debug("Base address '%s' found in '%s'", taddress,
                          present_reg)
                LOG.debug("Displacement needed: %s", displacement)

            else:

                present_reg = None
                displacement = None

            LOG.debug("Present_reg: %s", present_reg)
            LOG.debug("Displacement: %s", displacement)

            if present_reg is not None:

                if displacement != 0 and abs(displacement) < (2**15):

                    addi_ins = self.new_instruction("ADDI_V0")
                    addi_ins.set_operands(
                        [register, present_reg, displacement])
                    instrs.append(addi_ins)

                    LOG.debug("Computing directly from context (short)")

                    return instrs

                if present_reg != register:
                    or_ins = self.new_instruction("OR_V0")
                    or_ins.set_operands([present_reg, register, present_reg])
                    instrs.append(or_ins)

                if displacement != 0:
                    instrs += self.add_to_register(register, displacement)

                LOG.debug("Computing directly from context (long)")

                return instrs

        if context.symbolic and not force_absolute and not force_relative:

            # TODO: This should be a call to the environment object because
            # the implementation depends on the environment

            # Base address can be an instruction label (str) or
            # a Variable instance
            basename = address.base_address
            if not isinstance(address.base_address, str):
                basename = address.base_address.name

            lis_ins = self.new_instruction("ADDIS_V1")
            lis_ins.operands()[0].set_value(register)
            lis_ins.operands()[1].set_value(0)
            lis_ins.operands()[2].set_value("%s@highest" % basename,
                                            check=False)

            instrs.append(lis_ins)

            ori_ins = self.new_instruction("ORI_V0")
            ori_ins.operands()[0].set_value(register)
            ori_ins.operands()[1].set_value(register)
            ori_ins.operands()[2].set_value("%s@higher" % basename,
                                            check=False)
            instrs.append(ori_ins)

            rldicr_ins = self.new_instruction("RLDICR_V0")
            rldicr_ins.set_operands([register, register, 32, 31])
            instrs.append(rldicr_ins)

            oris_ins = self.new_instruction("ORIS_V0")
            oris_ins.operands()[0].set_value(register)
            oris_ins.operands()[1].set_value(register)
            oris_ins.operands()[2].set_value("%s@h" % basename, check=False)
            instrs.append(oris_ins)

            ori_ins = self.new_instruction("ORI_V0")
            ori_ins.operands()[0].set_value(register)
            ori_ins.operands()[1].set_value(register)
            ori_ins.operands()[2].set_value("%s@l" % basename, check=False)
            instrs.append(ori_ins)

            if address.displacement != 0:
                instrs += self.add_to_register(register, address.displacement)

            LOG.debug("End Loading symbolic reference")

            return instrs

        LOG.debug("Context not symbolic")

        base_address = address.base_address
        displacement = address.displacement

        LOG.debug("Base_address: %s", base_address)
        LOG.debug("Displacement: %s", displacement)

        if isinstance(base_address, Variable):
            LOG.debug("Get absolute address")
            displacement += base_address.address.displacement
            base_address = base_address.address.base_address

        LOG.debug("Base_address 2: %s", base_address)
        LOG.debug("Displacement 2: %s", displacement)

        if isinstance(base_address, str):

            if base_address == "data":
                base_address = Address(base_address=base_address)
            elif base_address == "code":
                base_address = InstructionAddress(base_address=base_address)

        source_register = None
        if context.register_has_value(base_address):
            source_register = context.registers_get_value(base_address)[0]
        else:

            for reg, value in context.register_values.items():
                if not isinstance(value, Address):
                    continue

                if (Address(base_address=value.base_address) ==
                        base_address.base_address):

                    source_register = reg
                    displacement += base_address.displacement
                    base_address = Address(
                        base_address=base_address.base_address)
                    break

                if value.base_address == base_address.base_address:
                    source_register = reg
                    displacement += base_address.displacement
                    base_address = Address(
                        base_address=base_address.base_address)
                    break

        if source_register is None or displacement >= (2**31):
            # Not source register found
            if base_address.base_address == "data":
                value = context.data_segment
            elif base_address.base_address == "code":
                value = context.code_segment
            else:
                LOG.debug(context.dump())
                raise MicroprobeCodeGenerationError(
                    "Unable to generate "
                    "the base address: '%s'"
                    " for target address: '%s'." % (base_address, address))

            if abs(displacement) >= (2**31):
                value = value + displacement
                displacement = 0

            assert (value is not None)

            instrs += self.set_register(register, value, context)

        if source_register is not None and source_register != register:
            or_ins = self.new_instruction("OR_V0")
            or_ins.set_operands([source_register, register, source_register])
            instrs.append(or_ins)

        if displacement != 0:
            instrs += self.add_to_register(register, displacement)

        LOG.debug("End address generation")
        return instrs
Exemplo n.º 19
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        caddress = InstructionAddress(base_address="code", displacement=0)

        # TODO: this is a hack, should not be done here. Once we implement
        # a proper code generation back-end, this will be fixed
        caddress += target.wrapper.init_main_pad()

        for instr in building_block.init:
            instr.set_address(caddress.copy())
            caddress += instr.architecture_type.format.length

        # TODO: this is a hack, should not be done here. Once we implement
        # a proper code generation back-end, this will be fixed
        caddress += target.wrapper.init_loop_pad()

        prev_bbl = None
        for bbl in building_block.cfg.bbls:

            if prev_bbl is not None:

                LOG.debug(prev_bbl.address)
                LOG.debug(prev_bbl.displacement)
                LOG.debug(bbl.address)
                LOG.debug(bbl.displacement)

                if bbl.displacement > 0 and prev_bbl.displacement > 0:
                    # Relative displacement
                    bbl.set_address(prev_bbl.address +
                                    (bbl.displacement - prev_bbl.displacement))
                else:
                    bbl.set_address(caddress + bbl.displacement)
            else:
                bbl.set_address(caddress + bbl.displacement)

            if caddress > bbl.address:
                raise MicroprobeCodeGenerationError("Overlapping BBLs?")

            caddress = bbl.address

            for instr in bbl.instrs:

                if instr.address is None or self._force:
                    instr.set_address(caddress.copy())
                    caddress += instr.architecture_type.format.length
                else:
                    caddress = instr.address + \
                        instr.architecture_type.format.length

            prev_bbl = bbl

        for instr in building_block.fini:
            instr.set_address(caddress.copy())
            caddress += instr.architecture_type.format.length

        # daddress = Address(base_address="data",
        #                   displacement=0)

        # for variable in building_block.registered_global_vars():
        #     LOG.debug(variable.address)
        #     daddress_var = daddress + variable.get_displacement()
        #     variable.set_address(daddress_var.copy())

        return []
Exemplo n.º 20
0
    def _wrap(self, bench):
        """Wrap a benchmark.

        This function wraps a benchmark using the synthesizer wrapper. The
        wrapping process is the process of converting the internal
        representation of the benchmark to the actual string that is written
        to a file, adding the necessary prologue and epilogue bytes of
        data.

        :param bench: Benchmark to wrap.
        :type bench: :class:`~.Benchmark`
        :return: A string representation of the benchmark
        :rtype: :class:`~.str`
        """
        self.wrapper.set_benchmark(bench)

        bench_str = []
        bench_str.append(self.wrapper.headers())

        instructions = []
        instructions_dict = {}
        instructions_next_dict = {}

        for instr in bench.init:
            instructions.append(instr)

        for bbl in bench.cfg.bbls:
            for instr in bbl.instrs:
                instructions.append(instr)

        for instr in bench.fini:
            instructions.append(instr)

        for instr in instructions:
            instructions_dict[instr.address] = instr
            if (instr.branch or instr.syscall or instr.trap):
                instructions_next_dict[instr.address] = \
                    instr.decorators['NI']['value']
            else:
                instructions_next_dict[instr.address] = \
                    instr.address + instr.architecture_type.format.length

        instr = instructions[0]
        if self._start_addr is not None:
            if "EA" in instr.decorators:
                instr = [
                    ins for ins in instructions
                    if int(ins.decorators["EA"]['value'][0], 16) ==
                    self._start_addr
                ][0]
            else:
                instr = instructions_dict[InstructionAddress(
                    base_address="code",
                    displacement=(self._start_addr -
                                  bench.context.code_segment))]

        count = 0

        cmd.cmdline.print_info("Maximum trace size: %s instructions " %
                               self._maxins)

        progress = Progress(self._maxins, msg="Instructions generated:")

        while True:

            count = count + 1

            if count > self._maxins:
                cmd.cmdline.print_info(
                    "Max number of instructions (%d) reached. "
                    "Stoping trace generation." % self._maxins)
                break

            try:
                instr_address = instructions_next_dict[instr.address]
                if not isinstance(instr_address, InstructionAddress):
                    instr_address = next(instr_address)

                next_instr = instructions_dict[instr_address]

            except KeyError:

                if instr.mnemonic.upper() == "ATTN":
                    cmd.cmdline.print_warning(
                        "Processor ATTN instruction found. Stopping trace "
                        "generation. ")
                    break

                cmd.cmdline.print_error(
                    "Jump from 0x%X to an unknown instruction in address "
                    "0x%X found. Stoping trace generation." %
                    (instr.address.displacement + bench.context.code_segment,
                     instr_address.displacement + bench.context.code_segment))
                exit(-1)

            progress()
            wrap_ins = self.wrapper.wrap_ins(instr,
                                             next_instr=next_instr,
                                             show=self._show_trace)

            bench_str.append(wrap_ins)

            instr = next_instr

        bench_str = [elem for elem in bench_str if elem != ""]
        return bench_str
Exemplo n.º 21
0
    def __call__(self, building_block, target):
        """

        :param building_block:
        :param target:

        """

        descriptors = self._model(building_block.code_size)

        current_displacement = 0
        orig_bbls = building_block.cfg.bbls[:]

        iteration_register = None
        first = True
        for idx, elem in enumerate(descriptors):
            chunks, displacement, iterations = elem

            LOG.debug("Descriptor info:")
            LOG.debug("  Chunks: %d", chunks)
            LOG.debug("  Displacement: %d", displacement)
            LOG.debug("  Iterations: %d", iterations)

            if chunks < 1 or iterations < 1:
                continue

            for dummy in range(0, iterations):

                first_chunk_in_iteration = None
                last_chunk_in_iteration = None

                for dummy in range(0, chunks):

                    if first:

                        LOG.debug("First Chunk - No copy")
                        first = False
                        current_chunk = orig_bbls
                        # prev_chunk = None

                    else:

                        LOG.debug("Other Chunk - Replicating")
                        # prev_chunk = current_chunk
                        current_chunk = replicate_bbls(
                            orig_bbls, displacement=current_displacement)

                        building_block.cfg.add_bbls(current_chunk)

                    if first_chunk_in_iteration is None:
                        first_chunk_in_iteration = current_chunk

                    last_chunk_in_iteration = current_chunk
                    current_displacement = current_displacement + displacement

            first_chunk_in_iteration = first_chunk_in_iteration[0]
            last_chunk_in_iteration = last_chunk_in_iteration[-1]

            if iterations > 1:

                LOG.debug("Adding loop control instructions")

                if iteration_register is None:

                    iteration_register = \
                        target.get_register_for_address_arithmetic(
                            building_block.context)
                    building_block.context.add_reserved_registers(
                        [iteration_register])

                    LOG.debug(
                        "Using register '%s' as loop control "
                        "register", iteration_register)

                # set the number of iteration to the first
                newins = target.set_register(iteration_register, 0,
                                             building_block.context)

                # pylint: disable=E1103
                first_chunk_in_iteration.insert_instr(
                    newins, before=first_chunk_in_iteration.instrs[0])
                # pylint: enable=E1103

                # set the branch to the last
                label = "chunk_%d" % (idx)

                newins = target.add_to_register(iteration_register, 1)
                newins += target.compare_and_branch(iteration_register,
                                                    iterations, "<", label,
                                                    building_block.context)

                # pylint: disable=E1103
                first_chunk_in_iteration.instrs[0].setlabel(label)

                last_chunk_in_iteration.insert_instr(
                    newins, after=last_chunk_in_iteration.instrs[-1])
                # pylint: enable=E1103

                # link_BBLS
        prev_bbl = None
        for bbl in building_block.cfg.bbls:

            if prev_bbl is not None:

                LOG.debug("Linking with previous chunk")
                source = InstructionAddress(
                    base_address="code",
                    displacement=prev_bbl.instrs[-1].address.displacement +
                    prev_bbl.instrs[-1].architecture_type.format.length)

                newins = target.branch_unconditional_relative(
                    source, bbl.instrs[0])

                prev_bbl.insert_instr([newins], after=prev_bbl.instrs[-1])
            prev_bbl = bbl