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