Exemple #1
0
    def get_missing_bytes(self, data, missing, reg_name, addr):
        name = "mem_" + str(addr) if self._id == 'mem' else "reg_" + str(reg_name) 
        obj = utils.get_unconstrained_bytes(self.state, name, missing * 8)
                
        # fix endness
        if self.category == 'reg' and self.state.arch.register_endness == 'Iend_LE':
            #self.log("reversing")
            obj = obj.reversed

        # fix endness
        if self.category != 'reg' and self.state.arch.memory_endness == 'Iend_LE':
            #self.log("reversing")
            obj = obj.reversed

        self.store(addr, obj, missing, ignore_endness=True)
        return (obj, None, None)
    def _merge_symbolic_addresses(self,
                                  others,
                                  merge_conditions,
                                  verbose=False):

        assert False  # ToDo
        if self.verbose: self.log("Merging symbolic addresses...", verbose)

        global n_ite

        count = 0
        all = [self] + others

        symbolic_memory = []
        formulas = {}

        # get all in-use symbolic addresses among all memories
        for k in range(len(all)):

            m = all[k]
            if self.verbose:
                self.log(
                    "\tSymbolic formulas in memory " + str(k) + ": " +
                    str(len(m._symbolic_memory)), verbose)
            for f, v, r in m._symbolic_memory:

                found = False
                for ff, V in formulas.items():

                    # do we have the same _exact_ formula?
                    if ff is f:

                        for vv, mems in V.items():
                            # same content?
                            if v.compare(vv):
                                mems.append(k)
                                found = True
                                break

                        if not found:
                            V[v] = [k]
                            found = True
                            break

                if not found:
                    formulas[f] = {v: [k]}

        if self.verbose:
            self.log(
                "\tSymbolic formulas among all memories: " +
                str(len(formulas)), verbose)

        if self.verbose: self.log("\tMerging symbolic addresses")
        count_same_address = 0
        for f, V in formulas.items():

            if len(V) == 1 and len(V[list(V.keys())[0]]) == len(all):
                # the same formula with the same content in all memories
                symbolic_memory.append([f, list(V.keys())[0], None])
                count_same_address += 1
                if self.verbose:
                    self.log(
                        "\tUnchanged: symbolic address " + str(f) + ": " +
                        str(symbolic_memory[-1][1].get_byte()), verbose)
                continue

            obj = utils.get_unconstrained_bytes(self.state,
                                                "bottom",
                                                8,
                                                memory=self)
            for v, mems in V.items():

                v = v.get_byte()
                cond = None
                for m in mems:
                    if cond is None:
                        cond = merge_conditions[m]
                    else:
                        cond = self.state.se.Or(cond, merge_conditions[m])

                n_ite += 1

                obj = self.state.se.If(cond, v, obj)

            if self.verbose:
                self.log(
                    "\tSymbolic address " + str(f) + " is replaced with: " +
                    str(obj), verbose)
            symbolic_memory.append([f, MemoryObject(obj, 0), None])

        if self.verbose:
            self.log(
                "\tSymbolic addresses that were the same on all memories:     "
                + str(count_same_address), verbose)
        if self.verbose:
            self.log(
                "\tSymbolic addresses that were not the same on all memories: "
                + str(len(symbolic_memory) - count_same_address), verbose)

        self._symbolic_memory = symbolic_memory

        return count
    def load(self,
             addr,
             size=None,
             condition=None,
             fallback=None,
             add_constraints=None,
             action=None,
             endness=None,
             inspect=True,
             ignore_endness=False,
             disable_actions=False):

        # ToDo
        # assert disable_actions

        global n_ite

        try:

            if self.verbose:
                self.log("Loading at " + str(addr) + " " + str(size) +
                         " bytes.")

            i_addr = addr
            i_size = size

            assert self._id == 'mem' or self._id == 'reg'

            addr, size, reg_name = self.memory_op(addr, size)

            if type(size) in (int, int):

                # concrete address
                if type(addr) in (int, int):
                    min_addr = addr
                    max_addr = addr

                # symbolic addr
                else:
                    min_addr = self.state.se.min_int(addr)
                    max_addr = self.state.se.max_int(addr)
                    if min_addr == max_addr:
                        addr = min_addr

                # check permissions
                self.check_sigsegv_and_refine(addr, min_addr, max_addr, False)

                data = None
                for k in range(size):

                    do_implicit_store = True
                    obj = utils.get_unconstrained_bytes(self.state,
                                                        "bottom",
                                                        8,
                                                        memory=self)
                    bottom = obj

                    if self.verbose:
                        self.log("\tLoading from: " + str(
                            hex(addr + k) if type(addr) in (int, int) else
                            (addr + k)))

                    # check versus concrete addresses
                    concrete_objs = self._concrete_memory.find(
                        min_addr + k,
                        max_addr + k)  # move this out of the loop and reuse it
                    if len(concrete_objs) == 1:

                        item = concrete_objs.popitem()
                        v = item[1].get_byte()
                        if min_addr == max_addr:  # constant addr
                            obj = v
                            do_implicit_store = False
                        else:
                            n_ite += 1
                            obj = self.state.se.If(addr + k == item[0], v, obj)

                    else:

                        addrs = []
                        concrete_addresses = sorted(concrete_objs.keys())
                        for i in range(len(concrete_addresses)):

                            concrete_addr = concrete_addresses[i]
                            addrs.append(concrete_addr)
                            v = concrete_objs[concrete_addr].get_byte()

                            # lookahead for merging
                            merged = False
                            if i + 1 < len(
                                    concrete_addresses
                            ) and concrete_addr + 1 == concrete_addresses[i +
                                                                          1]:

                                next_v = concrete_objs[concrete_addr +
                                                       1].get_byte()
                                if v.op == 'BVV':

                                    # both constant and equal
                                    if next_v.op == 'BVV' and v.args[
                                            0] == next_v.args[0]:
                                        #if self.verbose: self.log("\tmerging ite with same constant and consecutive address")
                                        merged = True

                                # same symbolic object
                                elif v is next_v:
                                    #if self.verbose: self.log("\tmerging ite with same sym and consecutive address")
                                    merged = True

                            if not merged:
                                if self.verbose:
                                    self.log("\tbuilding ite with " +
                                             str(len(addrs)) +
                                             " addresses")  # " + str(addrs))

                                obj = self.build_ite(addr + k, addrs, v, obj)
                                addrs = []

                        if len(addrs) > 0:
                            if self.verbose:
                                self.log("\tbuilding ite with " +
                                         str(len(addrs)) +
                                         " addresses")  #: "+ str(v))
                            obj = self.build_ite(addr + k, addrs, v, obj)
                            addrs = []

                    # check versus any symbolic address
                    formulas = self._symbolic_memory.query(
                        min_addr + k, max_addr + k)
                    for f in formulas:

                        e = f[2][0]
                        v = f[2][1]
                        range_e = [f[0], f[1]]

                        if self.intersect(e, addr + k, range_e,
                                          [min_addr + k, max_addr + k]):
                            if self.verbose:
                                self.log("\tadding ite with symbolic address"
                                         )  #: " + str(v))
                            try:

                                n_ite += 1
                                obj = self.state.se.If(e == addr + k,
                                                       v.get_byte(), obj)

                            except Exception as e:
                                print(str(e))
                                import pdb
                                pdb.set_trace()

                    if do_implicit_store:
                        if self.verbose:
                            self.log("\tDoing an implicit store...")
                        bottom = MemoryObject(bottom, 0)
                        if min_addr == max_addr:
                            self._concrete_memory[min_addr + k] = bottom
                        else:
                            self._symbolic_memory.add(
                                min_addr + k, max_addr + k, (addr + k, bottom)
                            )  # this is wrong, should be an ITE with all negated cases

                    # concat single-byte objs
                    if self.verbose:
                        self.log("\tappending data ")  # + str(obj))
                    data = self.state.se.Concat(
                        data, obj) if data is not None else obj

                # fix endness
                endness = self._endness if endness is None else endness
                if not ignore_endness and endness == "Iend_LE":
                    #if self.verbose: self.log("\treversing data: " + str(data))
                    data = data.reversed

                if not disable_actions:
                    if simuvex.o.AST_DEPS in self.state.options and self.category == 'reg':
                        r = simuvex.SimActionObject(data,
                                                    reg_deps=frozenset(
                                                        (addr, )))

                    if simuvex.o.AUTO_REFS in self.state.options and action is None:
                        ref_size = size if size is not None else (data.size() /
                                                                  8)
                        region_type = self.category
                        if region_type == 'file':
                            # Special handling for files to keep compatibility
                            # We may use some refactoring later
                            region_type = self.id
                        action = simuvex.SimActionData(self.state,
                                                       region_type,
                                                       'read',
                                                       addr=addr,
                                                       data=data,
                                                       size=ref_size,
                                                       condition=condition,
                                                       fallback=fallback)
                        self.state.log.add_action(action)

                if self.verbose: self.log("\treturning data ")  # + str(data))
                return data

            assert False

        except Exception as e:

            if type(e) in (simuvex.s_errors.SimSegfaultError, ):
                raise e

            print(str(e))
            import traceback
            traceback.print_exc()
            sys.exit(1)
    def _merge_concrete_addresses(self,
                                  others,
                                  merge_conditions,
                                  verbose=False):

        assert False
        global n_ite

        if self.verbose: self.log("Merging concrete addresses...")

        count = 0
        all = [self] + others

        # get all in-use addresses among all memories
        if self.verbose:
            self.log(
                "\tUsed addresses in 0: " +
                str(len(list(self._concrete_memory.keys()))), verbose)
        addresses = set(self._concrete_memory.keys())
        for k, o in enumerate(others):
            addresses |= set(o._concrete_memory.keys())
            if self.verbose:
                self.log(
                    "\tUsed addresses in " + str(k + 1) + ": " +
                    str(len(list(o._concrete_memory.keys()))), verbose)

        if self.verbose:
            self.log(
                "\tUsed addresses over " + str(len(all)) + " memories: " +
                str(len(addresses)), verbose)

        # for each address:
        #   - if it is in use in all memories and it has the same byte content then do nothing
        #   - otherwise map the address to an ite with all the possible contents + a bottom case
        if self.verbose:
            self.log("\tChecking addresses and updating them...", verbose)
        count_same_address = 0
        for addr in addresses:

            same_in_all = True
            values = []
            first_valid_value = None

            for k in range(len(all)):
                m = all[k]
                value = None
                if addr in m._concrete_memory:
                    value = m._concrete_memory[addr]
                    if k > 0 and values[0] is not None and not values[0].compare(
                            value
                    ):  # ToDo: it is correct to make a comparison? Expensive?
                        same_in_all = False
                else:
                    same_in_all = False

                values.append(value)

            if not same_in_all:
                obj = utils.get_unconstrained_bytes(self.state,
                                                    "bottom",
                                                    8,
                                                    memory=self)
                for k in range(len(values)):
                    value = values[k]
                    if value is None:
                        continue
                    value = value.get_byte()
                    obj = self.state.se.If(merge_conditions[k], value, obj)

                    n_ite += 1

                self._concrete_memory[addr] = MemoryObject(obj, 0)
                if self.verbose:
                    self.log(
                        "\tAddr " + str(hex(addr)) + " is replaced with: " +
                        str(obj), verbose)

            else:
                count_same_address += 1

        if self.verbose:
            self.log(
                "\tConcrete addresses that were the same on all memories:     "
                + str(count_same_address), verbose)
        if self.verbose:
            self.log(
                "\tConcrete addresses that were not the same on all memories: "
                + str(len(addresses) - count_same_address), verbose)

        return count