def _disassemble_bb(self, start, end, symbols):
        bb = BasicBlock()
        addr = start
        taken, not_taken, direct = None, None, None

        while addr < end:
            try:
                data_end = addr + self._arch_info.max_instruction_size
                data_chunk = self._memory[addr:min(data_end, end)]
                asm = self._disasm.disassemble(data_chunk, addr)
            except (DisassemblerError, InvalidAddressError,
                    InvalidDisassemblerData):
                logger.warning(
                    "Error while disassembling @ {:#x}".format(addr),
                    exc_info=True)
                break

            asm.ir_instrs = self._translator.translate(asm)

            bb.instrs.append(asm)

            # If it is a RET or HALT instruction, break.
            if self._arch_info.instr_is_ret(asm) or \
               self._arch_info.instr_is_halt(asm):
                bb.is_exit = True
                break

            # If it is a CALL instruction and the callee does not return, break.
            if self._arch_info.instr_is_call(asm):
                target = helper.extract_call_target(asm)

                if target and func_is_non_return(target, symbols):
                    bb.is_exit = True
                    break

            # If it is a BRANCH instruction, extract target and break.
            if self._arch_info.instr_is_branch(asm):
                target = helper.extract_branch_target(asm)

                if self._arch_info.instr_is_branch_cond(asm):
                    taken = target
                    not_taken = asm.address + asm.size
                else:
                    direct = target

                    # Jump to a function?
                    if direct in symbols:
                        bb.is_exit = True

                break

            # Update instruction pointer and iterate.
            addr += asm.size

        bb.taken_branch = taken
        bb.not_taken_branch = not_taken
        bb.direct_branch = direct

        return bb
示例#2
0
    def _disassemble_bb(self, start, end, symbols):
        bb = BasicBlock()
        addr = start
        taken, not_taken, direct = None, None, None

        while addr < end:
            try:
                data_end = addr + self._arch_info.max_instruction_size
                data_chunk = self._memory[addr:min(data_end, end)]
                asm = self._disasm.disassemble(data_chunk, addr)
            except (DisassemblerError, InvalidAddressError, InvalidDisassemblerData):
                logger.warn("Error while disassembling @ {:#x}".format(addr), exc_info=True)
                break

            ir = self._translator.translate(asm)

            bb.instrs.append(DualInstruction(addr, asm, ir))

            # If it is a RET or HALT instruction, break.
            if self._arch_info.instr_is_ret(asm) or \
               self._arch_info.instr_is_halt(asm):
                bb.is_exit = True
                break

            # If it is a CALL instruction and the callee does not return, break.
            if self._arch_info.instr_is_call(asm):
                target = helper.extract_call_target(asm)

                if target and func_is_non_return(target, symbols):
                    bb.is_exit = True
                    break

            # If it is a BRANCH instruction, extract target and break.
            if self._arch_info.instr_is_branch(asm):
                target = helper.extract_branch_target(asm)

                if self._arch_info.instr_is_branch_cond(asm):
                    taken = target
                    not_taken = asm.address + asm.size
                else:
                    direct = target

                    # Jump to a function?
                    if direct in symbols:
                        bb.is_exit = True

                break

            # Update instruction pointer and iterate.
            addr += asm.size

        bb.taken_branch = taken
        bb.not_taken_branch = not_taken
        bb.direct_branch = direct

        return bb
示例#3
0
    def _extract_call_targets(self, bbs):
        call_targets = []
        for bb in bbs:
            for dinstr in bb:
                if self._arch_info.instr_is_call(dinstr.asm_instr):
                    target = helper.extract_call_target(dinstr.asm_instr)

                    if target:
                        call_targets.append(target)

        return call_targets
示例#4
0
    def _extract_call_targets(self, bbs):
        call_targets = []
        for bb in bbs:
            for dinstr in bb:
                if self._arch_info.instr_is_call(dinstr.asm_instr):
                    target = helper.extract_call_target(dinstr.asm_instr)

                    if target:
                        call_targets.append(target)

        return call_targets