def patch_div(ir, instr, src1): # print '[*] Calling patched div.' e = [] size = src1.size if size == 8: src2 = mRAX[instr.mode][:16] elif size in [16, 32, 64]: s1, s2 = mRDX[size], mRAX[size] src2 = m2_expr.ExprCompose(s2, s1) else: raise ValueError('div arg not impl', src1) c_d = m2_expr.ExprOp('udiv', src2, src1.zeroExtend(src2.size)) c_r = m2_expr.ExprOp('umod', src2, src1.zeroExtend(src2.size)) # if 8 bit div, only ax is affected if size == 8: e.append( m2_expr.ExprAff(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) else: e.append(m2_expr.ExprAff(s1, c_r[:size])) e.append(m2_expr.ExprAff(s2, c_d[:size])) return e, []
def test_Variables_Identifier(self): import miasm2.expression.expression as m2_expr from miasm2.expression.expression_helper import Variables_Identifier # Build a complex expression cst = m2_expr.ExprInt16(0x100) eax = m2_expr.ExprId("EAX") ebx = m2_expr.ExprId("EBX") ax = eax[0:16] expr = eax + ebx expr = m2_expr.ExprCompose([(ax, 0, 16), (expr[16:32], 16, 32)]) expr2 = m2_expr.ExprMem((eax + ebx) ^ (eax), size=16) expr2 = expr2 | ax | expr2 | cst exprf = expr - expr + m2_expr.ExprCompose([(expr2, 0, 16), (cst, 16, 32)]) # Identify variables vi = Variables_Identifier(exprf) # Use __str__ print vi # Test the result new_expr = vi.equation ## Force replace in the variable dependency order for var_id, var_value in reversed(vi.vars.items()): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(exprf, new_expr)
def _set(self, dst, src): """ Special cases: * if dst is an ExprSlice, expand it to affect the full Expression * if dst already known, sources are merged """ if dst.size != src.size: raise RuntimeError("sanitycheck: args must have same size! %s" % ([(str(arg), arg.size) for arg in [dst, src]])) if isinstance(dst, m2_expr.ExprSlice): # Complete the source with missing slice parts new_dst = dst.arg rest = [(m2_expr.ExprSlice(dst.arg, r[0], r[1]), r[0], r[1]) for r in dst.slice_rest()] all_a = [(src, dst.start, dst.stop)] + rest all_a.sort(key=lambda x: x[1]) args = [expr for (expr, _, _) in all_a] new_src = m2_expr.ExprCompose(*args) else: new_dst, new_src = dst, src if new_dst in self._assigns and isinstance(new_src, m2_expr.ExprCompose): if not isinstance(self[new_dst], m2_expr.ExprCompose): # prev_RAX = 0x1122334455667788 # input_RAX[0:8] = 0x89 # final_RAX -> ? (assignment are in parallel) raise RuntimeError("Concurent access on same bit not allowed") # Consider slice grouping expr_list = [(new_dst, new_src), (new_dst, self[new_dst])] # Find collision e_colision = reduce(lambda x, y: x.union(y), (self.get_modified_slice(dst, src) for (dst, src) in expr_list), set()) # Sort interval collision known_intervals = sorted([(x[1], x[2]) for x in e_colision]) for i, (_, stop) in enumerate(known_intervals[:-1]): if stop > known_intervals[i + 1][0]: raise RuntimeError( "Concurent access on same bit not allowed") # Fill with missing data missing_i = get_missing_interval(known_intervals, 0, new_dst.size) remaining = ((m2_expr.ExprSlice(new_dst, *interval), interval[0], interval[1]) for interval in missing_i) # Build the merging expression args = list(e_colision.union(remaining)) args.sort(key=lambda x: x[1]) starts = [start for (_, start, _) in args] assert len(set(starts)) == len(starts) args = [expr for (expr, _, _) in args] new_src = m2_expr.ExprCompose(*args) self._assigns[new_dst] = new_src
def patch_rotate_with_carry_tpl(ir, instr, op, dst, src): # Compute results shifter = get_shift(dst, src).zeroExtend(dst.size + 1) result = m2_expr.ExprOp(op, m2_expr.ExprCompose(dst, cf), shifter) new_cf = result[dst.size:dst.size + 1] new_dst = result[:dst.size] result_trunc = result[:dst.size] if op == '<<<': of_value = result_trunc.msb() ^ new_cf else: of_value = (dst ^ result_trunc).msb() # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), of_value) # Build basic blocks e_do = [ m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, new_of), m2_expr.ExprAff(dst, new_dst) ] return (e_do, [])
def lui(ir, instr, a, b): """The immediate value @b is shifted left 16 bits and stored in the register @a. The lower 16 bits are zeroes.""" e = [] e.append(m2_expr.ExprAff(a, m2_expr.ExprCompose([(m2_expr.ExprInt16(0), 0, 16), (b[:16], 16, 32)]))) return e, []
def ins(ir, instr, a, b, c, d): e = [] pos = int(c) l = int(d) r = None if pos != 0: if l != 0: if pos + l != 32: r = m2_expr.ExprCompose(a[:pos], b[:l], a[pos + l:]) else: r = m2_expr.ExprCompose(a[:pos], b[:l]) else: if pos + l != 32: r = m2_expr.ExprCompose(a[:pos], a[pos + l:]) else: r = m2_expr.ExprCompose(a[:pos]) else: if l != 0: if pos + l != 32: r = m2_expr.ExprCompose(b[:l], a[pos + l:]) else: r = m2_expr.ExprCompose(b[:l]) else: if pos + l != 32: r = m2_expr.ExprCompose(a[pos + l:]) if r is not None: e.append(m2_expr.ExprAff(a, r)) return e, []
def merge_multi_affect(self, affect_list): """ If multiple affection to a same ExprId are present in @affect_list, merge them (in place). For instance, XCGH AH, AL semantic is [ RAX = {RAX[0:8],0,8, RAX[0:8],8,16, RAX[16:64],16,64} RAX = {RAX[8:16],0,8, RAX[8:64],8,64} ] This function will update @affect_list to replace previous ExprAff by [ RAX = {RAX[8:16],0,8, RAX[0:8],8,16, RAX[16:64],16,64} ] """ # Extract side effect effect = {} for expr in affect_list: effect[expr.dst] = effect.get(expr.dst, []) + [expr] # Find candidates for dst, expr_list in effect.items(): if len(expr_list) <= 1: continue # Only treat ExprCompose list if any(map(lambda e: not(isinstance(e.src, m2_expr.ExprCompose)), expr_list)): continue # Find collision e_colision = reduce(lambda x, y: x.union(y), (e.get_modified_slice() for e in expr_list), set()) # Sort interval collision known_intervals = sorted([(x[1], x[2]) for x in e_colision]) # Fill with missing data missing_i = get_missing_interval(known_intervals, 0, dst.size) remaining = ((m2_expr.ExprSlice(dst, *interval), interval[0], interval[1]) for interval in missing_i) # Build the merging expression slices = sorted(e_colision.union(remaining), key=lambda x: x[1]) final_dst = m2_expr.ExprCompose(slices) # Remove unused expression for expr in expr_list: affect_list.remove(expr) # Add the merged one affect_list.append(m2_expr.ExprAff(dst, final_dst))
def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0): """ Deep First evaluate nodes: 1. evaluate node's sons 2. simplify """ expr = self.expr_simp(expr) #print '\t'*level, "Eval:", expr if expr in cache: ret = cache[expr] #print "In cache!", ret elif expr.is_int(): return expr elif expr.is_id(): if isinstance(expr.name, asmblock.AsmLabel) and expr.name.offset is not None: ret = m2_expr.ExprInt(expr.name.offset, expr.size) else: ret = state.get(expr, expr) elif expr.is_mem(): ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = m2_expr.ExprMem(ptr, expr.size) ret = self.get_mem_state(ret) assert expr.size == ret.size elif expr.is_cond(): cond = self.apply_expr_on_state_visit_cache(expr.cond, state, cache, level+1) src1 = self.apply_expr_on_state_visit_cache(expr.src1, state, cache, level+1) src2 = self.apply_expr_on_state_visit_cache(expr.src2, state, cache, level+1) ret = m2_expr.ExprCond(cond, src1, src2) elif expr.is_slice(): arg = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = m2_expr.ExprSlice(arg, expr.start, expr.stop) elif expr.is_op(): args = [] for oarg in expr.args: arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level+1) assert oarg.size == arg.size args.append(arg) ret = m2_expr.ExprOp(expr.op, *args) elif expr.is_compose(): args = [] for arg in expr.args: args.append(self.apply_expr_on_state_visit_cache(arg, state, cache, level+1)) ret = m2_expr.ExprCompose(*args) else: raise TypeError("Unknown expr type") #print '\t'*level, "Result", ret ret = self.expr_simp(ret) #print '\t'*level, "Result simpl", ret assert expr.size == ret.size cache[expr] = ret return ret
def ins(ir, instr, a, b, c, d): e = [] pos = int(c) l = int(d) my_slices = [] if pos != 0: my_slices.append((a[:pos], 0, pos)) if l != 0: my_slices.append((b[:l], pos, pos + l)) if pos + l != 32: my_slices.append((a[pos + l:], pos + l, 32)) r = m2_expr.ExprCompose(my_slices) e.append(m2_expr.ExprAff(a, r)) return e, []
def compose(cls, size=32, depth=1): """Return an ExprCompose @size: (optional) Operation size @depth: (optional) Expression depth """ # First layer upper_bound = random.randint(1, size) args = [cls._gen(size=upper_bound, depth=depth - 1)] # Next layers while (upper_bound < size): if len(args) == (cls.compose_max_layer - 1): # We reach the maximum size new_upper_bound = size else: new_upper_bound = random.randint(upper_bound + 1, size) args.append(cls._gen(size=new_upper_bound - upper_bound)) upper_bound = new_upper_bound return m2_expr.ExprCompose(*args)
def compose(cls, size=32, depth=1): """Return an ExprCompose @size: (optional) Operation size @depth: (optional) Expression depth """ # First layer upper_bound = random.randint(1, size) args = [(cls._gen(size=upper_bound, depth=depth - 1), 0, upper_bound)] # Next layers while (upper_bound < size): if len(args) == (cls.compose_max_layer - 1): # We reach the maximum size upper_bound = size else: upper_bound = random.randint(args[-1][-1] + 1, size) args.append((cls._gen(size=upper_bound - args[-1][-1]), args[-1][-1], upper_bound)) return m2_expr.ExprCompose(args)
def get_mem_state(self, expr): """ Evaluate the @expr memory in the current state using @cache @expr: the memory key """ ptr, size = expr.arg, expr.size ret = self.find_mem_by_addr(ptr) if not ret: overlaps = self.get_mem_overlapping(expr) if not overlaps: if self.func_read and ptr.is_int(): expr = self.func_read(expr) return expr out = [] off_base = 0 for off, mem in overlaps: if off >= 0: new_size = min(size - off * 8, mem.size) tmp = self.expr_simp(self.symbols[mem][0:new_size]) out.append((tmp, off_base, off_base + new_size)) off_base += new_size else: new_size = min(size - off * 8, mem.size) tmp = self.expr_simp(self.symbols[mem][-off * 8:new_size]) new_off_base = off_base + new_size + off * 8 out.append((tmp, off_base, new_off_base)) off_base = new_off_base missing_slice = self.rest_slice(out, 0, size) for slice_start, slice_stop in missing_slice: ptr = self.expr_simp(ptr + m2_expr.ExprInt(slice_start / 8, ptr.size)) mem = m2_expr.ExprMem(ptr, slice_stop - slice_start) if self.func_read and ptr.is_int(): mem = self.func_read(mem) out.append((mem, slice_start, slice_stop)) out.sort(key=lambda x: x[1]) args = [expr for (expr, _, _) in out] ret = self.expr_simp(m2_expr.ExprCompose(*args)[:size]) return ret # bigger lookup if size > ret.size: rest = size out = [] while rest: mem = self.find_mem_by_addr(ptr) if mem is None: mem = m2_expr.ExprMem(ptr, 8) if self.func_read and ptr.is_int(): value = self.func_read(mem) else: value = mem elif rest >= mem.size: value = self.symbols[mem] else: value = self.symbols[mem][:rest] out.append(value) rest -= value.size ptr = self.expr_simp(ptr + m2_expr.ExprInt(mem.size / 8, ptr.size)) ret = self.expr_simp(m2_expr.ExprCompose(*out)) return ret # part lookup ret = self.expr_simp(self.symbols[ret][:size]) return ret
def possible_values(expr): """Return possible values for expression @expr, associated with their condition constraint as a ConstrainedValues instance @expr: Expr instance """ consvals = ConstrainedValues() # Terminal expression if (isinstance(expr, m2_expr.ExprInt) or isinstance(expr, m2_expr.ExprId)): consvals.add(ConstrainedValue(frozenset(), expr)) # Unary expression elif isinstance(expr, m2_expr.ExprSlice): consvals.update(ConstrainedValue(consval.constraints, consval.value[expr.start:expr.stop]) for consval in possible_values(expr.arg)) elif isinstance(expr, m2_expr.ExprMem): consvals.update(ConstrainedValue(consval.constraints, m2_expr.ExprMem(consval.value, expr.size)) for consval in possible_values(expr.arg)) elif isinstance(expr, m2_expr.ExprAff): consvals.update(possible_values(expr.src)) # Special case: constraint insertion elif isinstance(expr, m2_expr.ExprCond): to_ret = set() src1cond = CondConstraintNotZero(expr.cond) src2cond = CondConstraintZero(expr.cond) consvals.update(ConstrainedValue(consval.constraints.union([src1cond]), consval.value) for consval in possible_values(expr.src1)) consvals.update(ConstrainedValue(consval.constraints.union([src2cond]), consval.value) for consval in possible_values(expr.src2)) # N-ary expression elif isinstance(expr, m2_expr.ExprOp): # For details, see ExprCompose consvals_args = [possible_values(arg) for arg in expr.args] for consvals_possibility in itertools.product(*consvals_args): args_value = [consval.value for consval in consvals_possibility] args_constraint = itertools.chain(*[consval.constraints for consval in consvals_possibility]) consvals.add(ConstrainedValue(frozenset(args_constraint), m2_expr.ExprOp(expr.op, *args_value))) elif isinstance(expr, m2_expr.ExprCompose): # Generate each possibility for sub-argument, associated with the start # and stop bit consvals_args = [map(lambda x: x, possible_values(arg)) for arg in expr.args] for consvals_possibility in itertools.product(*consvals_args): # Merge constraint of each sub-element args_constraint = itertools.chain(*[consval.constraints for consval in consvals_possibility]) # Gen the corresponding constraints / ExprCompose args = [consval.value for consval in consvals_possibility] consvals.add( ConstrainedValue(frozenset(args_constraint), m2_expr.ExprCompose(*args))) else: raise RuntimeError("Unsupported type for expr: %s" % type(expr)) return consvals
def callback(self, jitter): # Check previous state is_symbolic = lambda expr: (isinstance(expr, m2_expr.ExprMem) and not isinstance(expr.arg, m2_expr.ExprInt)) # When it is possible, consider only elements modified in the last run # -> speed up to avoid browsing the whole memory to_consider = self.symb.modified_exprs for symbol in to_consider: # Do not consider PC if symbol == self.ira.pc: continue # Write to @NN[... argX ...] if is_symbolic(symbol): self.memories_write.add(symbol) # Read from ... @NN[... argX ...] ... symb_value = self.symb.eval_expr(symbol) to_replace = {} for expr in m2_expr.ExprAff(symbol, symb_value).get_r(mem_read=True): if is_symbolic(expr): if isinstance(expr, m2_expr.ExprMem): # Consider each byte individually # Case: @32[X] with only @8[X+1] to replace addr_expr = expr.arg new_expr = [] consider = False for offset in xrange(expr.size / 8): sub_expr = m2_expr.ExprMem( self.symb.expr_simp( addr_expr + m2_expr.ExprInt( offset, size=addr_expr.size)), 8) if not self.is_pointer(sub_expr): # Not a PTR, we have to replace with the real value original_sub_expr = sub_expr.replace_expr( self.init_values) new_expr.append( self.symb.eval_expr(original_sub_expr)) consider = True else: new_expr.append(sub_expr) # Rebuild the corresponding expression if consider: assert len(new_expr) == expr.size / 8 to_replace[expr] = m2_expr.ExprCompose(*new_expr) if expr not in self.memories_write: # Do not consider memory already written during the run self.memories_read.add(expr) # Replace with real value for non-pointer symbols if to_replace: symb_value = self.symb.expr_simp( symb_value.replace_expr(to_replace)) if isinstance(symbol, m2_expr.ExprMem): # Replace only in ptr (case to_replace: @[arg] = 8, expr: # @[arg] = @[arg]) symbol = m2_expr.ExprMem( self.symb.expr_simp( symbol.arg.replace_expr(to_replace)), symbol.size) self.symb.apply_change(symbol, symb_value) # Check computed values against real ones # TODO idem memory if (isinstance(symbol, m2_expr.ExprId) and isinstance(symb_value, m2_expr.ExprInt)): if hasattr(jitter.cpu, symbol.name): value = m2_expr.ExprInt(getattr(jitter.cpu, symbol.name), symbol.size) assert value == self.symb.symbols[symbol] cur_addr = jitter.pc self.logger.debug("Current address: %s", hex(cur_addr)) if cur_addr == 0x1337BEEF or cur_addr == self.return_addr: # End reached if self.logger.isEnabledFor(logging.DEBUG): print "In:" for x in self.memories_read: print "\t%s (%s)" % ( x, self.c_handler.expr_to_c(x), ) print "Out:" for x in self.memories_write: print "\t%s (%s)" % ( x, self.c_handler.expr_to_c(x), ) return True # Update state ## Reset cache structures self.mdis.job_done.clear() self.symb_ir.blocs.clear() ## Update current state asm_block = self.mdis.dis_bloc(cur_addr) irblocks = self.symb_ir.add_bloc(asm_block) self.symb.emul_ir_blocks(cur_addr) return True
def eval_ExprMem(self, e, eval_cache=None): if eval_cache is None: eval_cache = {} a_val = self.expr_simp(self.eval_expr(e.arg, eval_cache)) if a_val != e.arg: a = self.expr_simp(m2_expr.ExprMem(a_val, size=e.size)) else: a = e if a in self.symbols: return self.symbols[a] tmp = None # test if mem lookup is known if a_val in self.symbols.symbols_mem: tmp = self.symbols.symbols_mem[a_val][0] if tmp is None: v = self.find_mem_by_addr(a_val) if not v: out = [] ov = self.get_mem_overlapping(a, eval_cache) off_base = 0 ov.sort() # ov.reverse() for off, x in ov: # off_base = off * 8 # x_size = self.symbols[x].size if off >= 0: m = min(a.size - off * 8, x.size) ee = m2_expr.ExprSlice(self.symbols[x], 0, m) ee = self.expr_simp(ee) out.append((ee, off_base, off_base + m)) off_base += m else: m = min(a.size - off * 8, x.size) ee = m2_expr.ExprSlice(self.symbols[x], -off * 8, m) ff = self.expr_simp(ee) new_off_base = off_base + m + off * 8 out.append((ff, off_base, new_off_base)) off_base = new_off_base if out: missing_slice = self.rest_slice(out, 0, a.size) for sa, sb in missing_slice: ptr = self.expr_simp( a_val + m2_expr.ExprInt_from(a_val, sa / 8)) mm = m2_expr.ExprMem(ptr, size=sb - sa) mm.is_term = True mm.is_simp = True out.append((mm, sa, sb)) out.sort(key=lambda x: x[1]) # for e, sa, sb in out: # print str(e), sa, sb ee = m2_expr.ExprSlice(m2_expr.ExprCompose(out), 0, a.size) ee = self.expr_simp(ee) return ee if self.func_read and isinstance(a.arg, m2_expr.ExprInt): return self.func_read(a) else: # XXX hack test a.is_term = True return a # bigger lookup if a.size > tmp.size: rest = a.size ptr = a_val out = [] ptr_index = 0 while rest: v = self.find_mem_by_addr(ptr) if v is None: # raise ValueError("cannot find %s in mem"%str(ptr)) val = m2_expr.ExprMem(ptr, 8) v = val diff_size = 8 elif rest >= v.size: val = self.symbols[v] diff_size = v.size else: diff_size = rest val = self.symbols[v][0:diff_size] val = (val, ptr_index, ptr_index + diff_size) out.append(val) ptr_index += diff_size rest -= diff_size ptr = self.expr_simp( self.eval_expr( m2_expr.ExprOp('+', ptr, m2_expr.ExprInt_from(ptr, v.size / 8)), eval_cache)) e = self.expr_simp(m2_expr.ExprCompose(out)) return e # part lookup tmp = self.expr_simp(m2_expr.ExprSlice(self.symbols[tmp], 0, a.size)) return tmp
def wsbh(ir, instr, a, b): e = [m2_expr.ExprAff(a, m2_expr.ExprCompose([(b[8:16], 0, 8), (b[0:8] , 8, 16), (b[24:32], 16, 24), (b[16:24], 24, 32)]))] return e, []
def extr(arg1, arg2, arg3, arg4): compose = m2_expr.ExprCompose([(arg2, 0, arg2.size), (arg3, arg2.size, arg2.size + arg3.size)]) arg1 = compose[int(arg4.arg):int(arg4.arg) + arg1.size]
def test_Variables_Identifier(self): import miasm2.expression.expression as m2_expr from miasm2.expression.expression_helper import Variables_Identifier # Build a complex expression cst = m2_expr.ExprInt16(0x100) eax = m2_expr.ExprId("EAX") ebx = m2_expr.ExprId("EBX") ax = eax[0:16] expr = eax + ebx expr = m2_expr.ExprCompose(ax, expr[16:32]) expr2 = m2_expr.ExprMem((eax + ebx) ^ (eax), size=16) expr2 = expr2 | ax | expr2 | cst exprf = expr - expr + m2_expr.ExprCompose(expr2, cst) # Identify variables vi = Variables_Identifier(exprf) # Use __str__ print vi # Test the result new_expr = vi.equation ## Force replace in the variable dependency order for var_id, var_value in reversed(vi.vars.items()): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(exprf, new_expr) # Test prefix vi = Variables_Identifier(exprf, var_prefix="prefix_v") ## Use __str__ print vi ## Test the result new_expr = vi.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(vi.vars.items()): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(exprf, new_expr) # Test an identify on an expression already containing identifier vi = Variables_Identifier(exprf) vi2 = Variables_Identifier(vi.equation) ## Test the result new_expr = vi2.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(vi2.vars.items()): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(vi.equation, new_expr) ## Corner case: each sub var depends on itself mem1 = m2_expr.ExprMem(ebx, size=32) mem2 = m2_expr.ExprMem(mem1, size=32) cst2 = m2_expr.ExprInt32(-1) expr_mini = ((eax ^ mem2 ^ cst2) & (mem2 ^ (eax + mem2)))[31:32] ## Build vi = Variables_Identifier(expr_mini) vi2 = Variables_Identifier(vi.equation) ## Test the result new_expr = vi2.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(vi2.vars.items()): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(vi.equation, new_expr)
def get_mem_state(self, expr): """ Evaluate the @expr memory in the current state using @cache @expr: the memory key """ ptr, size = expr.arg, expr.size ret = self.find_mem_by_addr(ptr) if not ret: out = [] overlaps = self.get_mem_overlapping(expr) off_base = 0 for off, mem in overlaps: if off >= 0: new_size = min(size - off * 8, mem.size) tmp = self.expr_simp(self.symbols[mem][0:new_size]) out.append((tmp, off_base, off_base + new_size)) off_base += new_size else: new_size = min(size - off * 8, mem.size) tmp = self.expr_simp(self.symbols[mem][-off * 8:new_size]) new_off_base = off_base + new_size + off * 8 out.append((tmp, off_base, new_off_base)) off_base = new_off_base if out: missing_slice = self.rest_slice(out, 0, size) for slice_start, slice_stop in missing_slice: ptr = self.expr_simp( ptr + m2_expr.ExprInt(slice_start / 8, ptr.size)) mem = m2_expr.ExprMem(ptr, slice_stop - slice_start) out.append((mem, slice_start, slice_stop)) out.sort(key=lambda x: x[1]) args = [expr for (expr, _, _) in out] tmp = m2_expr.ExprSlice(m2_expr.ExprCompose(*args), 0, size) tmp = self.expr_simp(tmp) return tmp if self.func_read and isinstance(ptr, m2_expr.ExprInt): return self.func_read(expr) else: return expr # bigger lookup if size > ret.size: rest = size ptr = ptr out = [] ptr_index = 0 while rest: mem = self.find_mem_by_addr(ptr) if mem is None: value = m2_expr.ExprMem(ptr, 8) mem = value diff_size = 8 elif rest >= mem.size: value = self.symbols[mem] diff_size = mem.size else: diff_size = rest value = self.symbols[mem][0:diff_size] out.append((value, ptr_index, ptr_index + diff_size)) ptr_index += diff_size rest -= diff_size ptr = self.expr_simp(ptr + m2_expr.ExprInt(mem.size / 8, ptr.size)) out.sort(key=lambda x: x[1]) args = [expr for (expr, _, _) in out] ret = self.expr_simp(m2_expr.ExprCompose(*args)) return ret # part lookup ret = self.expr_simp(self.symbols[ret][:size]) return ret
def extr(arg1, arg2, arg3, arg4): compose = m2_expr.ExprCompose(arg2, arg3) arg1 = compose[int(arg4.arg):int(arg4)+arg1.size]