diff options
| author | serpilliere <fabrice.desclaux@cea.fr> | 2015-02-21 21:34:52 +0100 |
|---|---|---|
| committer | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2016-11-04 16:45:46 +0100 |
| commit | 895263f702876a2cdf3bd1e9359ce1b0340f87fd (patch) | |
| tree | 23135227a64390adcf153120f841d28f4d2ed530 | |
| parent | 8e8a60b5d55db6209d05577d038ed3b4dc961b60 (diff) | |
| download | miasm-895263f702876a2cdf3bd1e9359ce1b0340f87fd.tar.gz miasm-895263f702876a2cdf3bd1e9359ce1b0340f87fd.zip | |
Expression: remove is_term attribute
| -rw-r--r-- | miasm2/analysis/data_analysis.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/sh4/regs.py | 1 | ||||
| -rw-r--r-- | miasm2/arch/x86/regs.py | 1 | ||||
| -rw-r--r-- | miasm2/expression/expression.py | 248 | ||||
| -rw-r--r-- | miasm2/expression/expression_helper.py | 10 | ||||
| -rw-r--r-- | miasm2/ir/analysis.py | 7 | ||||
| -rw-r--r-- | miasm2/ir/symbexec.py | 603 | ||||
| -rw-r--r-- | test/ir/symbexec.py | 24 |
8 files changed, 435 insertions, 466 deletions
diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py index 88f9b680..9fee22af 100644 --- a/miasm2/analysis/data_analysis.py +++ b/miasm2/analysis/data_analysis.py @@ -75,12 +75,7 @@ def intra_bloc_flow_symbexec(ir_arch, flow_graph, irb): out_nodes = {} current_nodes = {} - symbols_init = {} - for r in ir_arch.arch.regs.all_regs_ids: - # symbols_init[r] = ir_arch.arch.regs.all_regs_ids_init[i] - x = ExprId(r.name, r.size) - x.is_term = True - symbols_init[r] = x + symbols_init = dict(ir_arch.arch.regs.all_regs_ids_init) sb = symbexec(ir_arch, dict(symbols_init)) sb.emulbloc(irb) diff --git a/miasm2/arch/sh4/regs.py b/miasm2/arch/sh4/regs.py index cfbca187..89ff42f8 100644 --- a/miasm2/arch/sh4/regs.py +++ b/miasm2/arch/sh4/regs.py @@ -78,7 +78,6 @@ all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids] regs_init = {} for i, r in enumerate(all_regs_ids): - all_regs_ids_init[i].is_term = True regs_init[r] = all_regs_ids_init[i] regs_flt_expr = [] diff --git a/miasm2/arch/x86/regs.py b/miasm2/arch/x86/regs.py index 18083a04..34585dae 100644 --- a/miasm2/arch/x86/regs.py +++ b/miasm2/arch/x86/regs.py @@ -430,7 +430,6 @@ all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids] regs_init = {} for i, r in enumerate(all_regs_ids): - all_regs_ids_init[i].is_term = True regs_init[r] = all_regs_ids_init[i] regs_flt_expr = [float_st0, float_st1, float_st2, float_st3, diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py index ad76f01c..59e809a5 100644 --- a/miasm2/expression/expression.py +++ b/miasm2/expression/expression.py @@ -114,18 +114,12 @@ class Expr(object): "Parent class for Miasm Expressions" - __slots__ = ["is_term", "is_simp", "is_canon", - "is_eval", "__hash", "__repr", "__size", - "is_var_ident"] - all_exprs = set() args2expr = {} simp_exprs = set() canon_exprs = set() use_singleton = True - is_term = False # Terminal expression - def set_size(self, value): raise ValueError('size is not mutable') @@ -134,7 +128,7 @@ class Expr(object): self.__repr = None self.__size = None - size = property(lambda self: self._size) + size = property(lambda self: self.__size) @staticmethod def get_object(cls, args): @@ -191,9 +185,9 @@ class Expr(object): return False def __repr__(self): - if self._repr is None: - self._repr = self._exprrepr() - return self._repr + if self.__repr is None: + self.__repr = self._exprrepr() + return self.__repr def __hash__(self): if self.__hash is None: @@ -379,7 +373,6 @@ class ExprInt(Expr): - Constant 0x12345678 on 32bits """ - __slots__ = ["__arg"] def __init__(self, num, size=None): """Create an ExprInt from a modint or num/size @@ -389,31 +382,30 @@ class ExprInt(Expr): super(ExprInt, self).__init__() if is_modint(num): - self._arg = num - self._size = self.arg.size + self.__arg = num + self.__size = self.arg.size if size is not None and num.size != size: raise RuntimeError("size must match modint size") elif size is not None: - self._arg = mod_size2uint[size](num) - self._size = self.arg.size + self.__arg = mod_size2uint[size](num) + self.__size = self.arg.size else: raise ValueError('arg must by modint or (int,size)! %s' % num) - self.__arg = arg - self.__size = self.arg.size - size = property(lambda self: self.__size) arg = property(lambda self: self.__arg) - def __new__(cls, arg): - return Expr.get_object(cls, (arg, arg.size)) + def __new__(cls, arg, size=None): + if size is None: + size = arg.size + return Expr.get_object(cls, (arg, size)) def __get_int(self): "Return self integer representation" - return int(self._arg & size2mask(self._size)) + return int(self.__arg & size2mask(self.__size)) def __str__(self): - if self._arg < 0: + if self.__arg < 0: return str("-0x%X" % (- self.__get_int())) else: return str("0x%X" % self.__get_int()) @@ -428,7 +420,7 @@ class ExprInt(Expr): return set() def _exprhash(self): - return hash((EXPRINT, self._arg, self._size)) + return hash((EXPRINT, self.__arg, self.__size)) def _exprrepr(self): return "%s(0x%X)" % (self.__class__.__name__, self.__get_int()) @@ -441,7 +433,7 @@ class ExprInt(Expr): return self def copy(self): - return ExprInt(self._arg) + return ExprInt(self.__arg) def depth(self): return 1 @@ -466,7 +458,6 @@ class ExprId(Expr): - variable v1 """ - __slots__ = ["_name"] def __init__(self, name, size=32): """Create an identifier @@ -476,7 +467,6 @@ class ExprId(Expr): super(ExprId, self).__init__() self.__name, self.__size = name, size - self.is_term = is_term size = property(lambda self: self.__size) name = property(lambda self: self.__name) @@ -485,7 +475,7 @@ class ExprId(Expr): return Expr.get_object(cls, (name, size)) def __str__(self): - return str(self._name) + return str(self.__name) def get_r(self, mem_read=False, cst_read=False): return set([self]) @@ -525,7 +515,6 @@ class ExprAff(Expr): - var1 <- 2 """ - __slots__ = ["_src", "_dst"] def __init__(self, dst, src): """Create an ExprAff for dst <- src @@ -562,41 +551,41 @@ class ExprAff(Expr): return Expr.get_object(cls, (dst, src)) def __str__(self): - return "%s = %s" % (str(self._dst), str(self._src)) + return "%s = %s" % (str(self.__dst), str(self.__src)) def get_r(self, mem_read=False, cst_read=False): - elements = self._src.get_r(mem_read, cst_read) - if isinstance(self._dst, ExprMem) and mem_read: - elements.update(self._dst.arg.get_r(mem_read, cst_read)) + elements = self.__src.get_r(mem_read, cst_read) + if isinstance(self.__dst, ExprMem) and mem_read: + elements.update(self.__dst.arg.get_r(mem_read, cst_read)) return elements def get_w(self): - if isinstance(self._dst, ExprMem): - return set([self._dst]) # [memreg] + if isinstance(self.__dst, ExprMem): + return set([self.__dst]) # [memreg] else: - return self._dst.get_w() + return self.__dst.get_w() def _exprhash(self): - return hash((EXPRAFF, hash(self._dst), hash(self._src))) + return hash((EXPRAFF, hash(self.__dst), hash(self.__src))) def _exprrepr(self): - return "%s(%r, %r)" % (self.__class__.__name__, self._dst, self._src) + return "%s(%r, %r)" % (self.__class__.__name__, self.__dst, self.__src) def __contains__(self, expr): return (self == expr or - self._src.__contains__(expr) or - self._dst.__contains__(expr)) + self.__src.__contains__(expr) or + self.__dst.__contains__(expr)) # XXX /!\ for hackish expraff to slice def get_modified_slice(self): """Return an Expr list of extra expressions needed during the object instanciation""" - dst = self._dst - if not isinstance(self._src, ExprCompose): + dst = self.__dst + if not isinstance(self.__src, ExprCompose): raise ValueError("Get mod slice not on expraff slice", str(self)) modified_s = [] - for arg in self._src.args: + for arg in self.__src.args: if (not isinstance(arg[0], ExprSlice) or arg[0].arg != dst or arg[1] != arg[0].start or @@ -607,21 +596,21 @@ class ExprAff(Expr): @visit_chk def visit(self, cb, tv=None): - dst, src = self._dst.visit(cb, tv), self._src.visit(cb, tv) - if dst == self._dst and src == self._src: + dst, src = self.__dst.visit(cb, tv), self.__src.visit(cb, tv) + if dst == self.__dst and src == self.__src: return self else: return ExprAff(dst, src) def copy(self): - return ExprAff(self._dst.copy(), self._src.copy()) + return ExprAff(self.__dst.copy(), self.__src.copy()) def depth(self): - return max(self._src.depth(), self._dst.depth()) + 1 + return max(self.__src.depth(), self.__dst.depth()) + 1 def graph_recursive(self, graph): graph.add_node(self) - for arg in [self._src, self._dst]: + for arg in [self.__src, self.__dst]: arg.graph_recursive(graph) graph.add_uniq_edge(self, arg) @@ -636,7 +625,6 @@ class ExprCond(Expr): - if (cond) then ... else ... """ - __slots__ = ["_cond", "_src1", "_src2"] def __init__(self, cond, src1, src2): """Create an ExprCond @@ -660,7 +648,7 @@ class ExprCond(Expr): return Expr.get_object(cls, (cond, src1, src2)) def __str__(self): - return "(%s?(%s,%s))" % (str(self._cond), str(self._src1), str(self._src2)) + return "(%s?(%s,%s))" % (str(self.__cond), str(self.__src1), str(self.__src2)) def get_r(self, mem_read=False, cst_read=False): out_src1 = self.src1.get_r(mem_read, cst_read) @@ -673,11 +661,11 @@ class ExprCond(Expr): def _exprhash(self): return hash((EXPRCOND, hash(self.cond), - hash(self._src1), hash(self._src2))) + hash(self.__src1), hash(self.__src2))) def _exprrepr(self): return "%s(%r, %r, %r)" % (self.__class__.__name__, - self._cond, self._src1, self._src2) + self.__cond, self.__src1, self.__src2) def __contains__(self, e): return (self == e or @@ -687,28 +675,28 @@ class ExprCond(Expr): @visit_chk def visit(self, cb, tv=None): - cond = self._cond.visit(cb, tv) - src1 = self._src1.visit(cb, tv) - src2 = self._src2.visit(cb, tv) - if (cond == self._cond and - src1 == self._src1 and - src2 == self._src2): + cond = self.__cond.visit(cb, tv) + src1 = self.__src1.visit(cb, tv) + src2 = self.__src2.visit(cb, tv) + if (cond == self.__cond and + src1 == self.__src1 and + src2 == self.__src2): return self return ExprCond(cond, src1, src2) def copy(self): - return ExprCond(self._cond.copy(), - self._src1.copy(), - self._src2.copy()) + return ExprCond(self.__cond.copy(), + self.__src1.copy(), + self.__src2.copy()) def depth(self): - return max(self._cond.depth(), - self._src1.depth(), - self._src2.depth()) + 1 + return max(self.__cond.depth(), + self.__src1.depth(), + self.__src2.depth()) + 1 def graph_recursive(self, graph): graph.add_node(self) - for arg in [self._cond, self._src1, self._src2]: + for arg in [self.__cond, self.__src1, self.__src2]: arg.graph_recursive(graph) graph.add_uniq_edge(self, arg) @@ -722,7 +710,6 @@ class ExprMem(Expr): - Memory write """ - __slots__ = ["_arg", "_size"] def __init__(self, arg, size=32): """Create an ExprMem @@ -749,7 +736,7 @@ class ExprMem(Expr): def get_r(self, mem_read=False, cst_read=False): if mem_read: - return set(self._arg.get_r(mem_read, cst_read).union(set([self]))) + return set(self.__arg.get_r(mem_read, cst_read).union(set([self]))) else: return set([self]) @@ -757,19 +744,19 @@ class ExprMem(Expr): return set([self]) # [memreg] def _exprhash(self): - return hash((EXPRMEM, hash(self._arg), self._size)) + return hash((EXPRMEM, hash(self.__arg), self.__size)) def _exprrepr(self): return "%s(%r, %r)" % (self.__class__.__name__, - self._arg, self._size) + self.__arg, self.__size) def __contains__(self, expr): - return self == expr or self._arg.__contains__(expr) + return self == expr or self.__arg.__contains__(expr) @visit_chk def visit(self, cb, tv=None): - arg = self._arg.visit(cb, tv) - if arg == self._arg: + arg = self.__arg.visit(cb, tv) + if arg == self.__arg: return self return ExprMem(arg, self.size) @@ -778,15 +765,15 @@ class ExprMem(Expr): return ExprMem(arg, size=self.size) def is_op_segm(self): - return isinstance(self._arg, ExprOp) and self._arg.op == 'segm' + return isinstance(self.__arg, ExprOp) and self.__arg.op == 'segm' def depth(self): - return self._arg.depth() + 1 + return self.__arg.depth() + 1 def graph_recursive(self, graph): graph.add_node(self) - self._arg.graph_recursive(graph) - graph.add_uniq_edge(self, self._arg) + self.__arg.graph_recursive(graph) + graph.add_uniq_edge(self, self.__arg) class ExprOp(Expr): @@ -799,7 +786,6 @@ class ExprOp(Expr): - parity bit(var1) """ - __slots__ = ["_op", "_args"] def __init__(self, op, *args): """Create an ExprOp @@ -821,7 +807,7 @@ class ExprOp(Expr): if not isinstance(op, str): raise ValueError("ExprOp: 'op' argument must be a string") - self.__op, self._args = op, tuple(args) + self.__op, self.__args = op, tuple(args) # Set size for special cases if self.__op in [ @@ -858,7 +844,7 @@ class ExprOp(Expr): 'double_trunc_to_int_80']: sz = 80 elif self.__op in ['segm']: - sz = self._args[1].size + sz = self.__args[1].size else: if None in sizes: sz = None @@ -877,19 +863,19 @@ class ExprOp(Expr): def __str__(self): if self.is_associative(): - return '(' + self._op.join([str(arg) for arg in self._args]) + ')' - if (self._op.startswith('call_func_') or - self._op == 'cpuid' or - len(self._args) > 2 or - self._op in ['parity', 'segm']): - return self._op + '(' + ', '.join([str(arg) for arg in self._args]) + ')' - if len(self._args) == 2: - return ('(' + str(self._args[0]) + - ' ' + self.op + ' ' + str(self._args[1]) + ')') + return '(' + self.__op.join([str(arg) for arg in self.__args]) + ')' + if (self.__op.startswith('call_func_') or + self.__op == 'cpuid' or + len(self.__args) > 2 or + self.__op in ['parity', 'segm']): + return self.__op + '(' + ', '.join([str(arg) for arg in self.__args]) + ')' + if len(self.__args) == 2: + return ('(' + str(self.__args[0]) + + ' ' + self.op + ' ' + str(self.__args[1]) + ')') else: return reduce(lambda x, y: x + ' ' + str(y), - self._args, - '(' + str(self._op)) + ')' + self.__args, + '(' + str(self.__op)) + ')' def get_r(self, mem_read=False, cst_read=False): return reduce(lambda elements, arg: @@ -899,58 +885,57 @@ class ExprOp(Expr): raise ValueError('op cannot be written!', self) def _exprhash(self): - h_hargs = [hash(arg) for arg in self._args] - return hash((EXPROP, self._op, tuple(h_hargs))) + h_hargs = [hash(arg) for arg in self.__args] + return hash((EXPROP, self.__op, tuple(h_hargs))) def _exprrepr(self): - return "%s(%r, %s)" % (self.__class__.__name__, self._op, - ', '.join(repr(arg) for arg in self._args)) + return "%s(%r, %s)" % (self.__class__.__name__, self.__op, + ', '.join(repr(arg) for arg in self.__args)) def __contains__(self, e): if self == e: return True - for arg in self._args: + for arg in self.__args: if arg.__contains__(e): return True return False def is_function_call(self): - return self._op.startswith('call') + return self.__op.startswith('call') def is_associative(self): "Return True iff current operation is associative" - return (self._op in ['+', '*', '^', '&', '|']) + return (self.__op in ['+', '*', '^', '&', '|']) def is_commutative(self): "Return True iff current operation is commutative" - return (self._op in ['+', '*', '^', '&', '|']) + return (self.__op in ['+', '*', '^', '&', '|']) @visit_chk def visit(self, cb, tv=None): - args = [arg.visit(cb, tv) for arg in self._args] - modified = any([arg[0] != arg[1] for arg in zip(self._args, args)]) + args = [arg.visit(cb, tv) for arg in self.__args] + modified = any([arg[0] != arg[1] for arg in zip(self.__args, args)]) if modified: - return ExprOp(self._op, *args) + return ExprOp(self.__op, *args) return self def copy(self): - args = [arg.copy() for arg in self._args] - return ExprOp(self._op, *args) + args = [arg.copy() for arg in self.__args] + return ExprOp(self.__op, *args) def depth(self): - depth = [arg.depth() for arg in self._args] + depth = [arg.depth() for arg in self.__args] return max(depth) + 1 def graph_recursive(self, graph): graph.add_node(self) - for arg in self._args: + for arg in self.__args: arg.graph_recursive(graph) graph.add_uniq_edge(self, arg) class ExprSlice(Expr): - __slots__ = ["_arg", "_start", "_stop"] def __init__(self, arg, start, stop): super(ExprSlice, self).__init__() @@ -968,20 +953,20 @@ class ExprSlice(Expr): return Expr.get_object(cls, (arg, start, stop)) def __str__(self): - return "%s[%d:%d]" % (str(self._arg), self._start, self._stop) + return "%s[%d:%d]" % (str(self.__arg), self.__start, self.__stop) def get_r(self, mem_read=False, cst_read=False): - return self._arg.get_r(mem_read, cst_read) + return self.__arg.get_r(mem_read, cst_read) def get_w(self): - return self._arg.get_w() + return self.__arg.get_w() def _exprhash(self): - return hash((EXPRSLICE, hash(self._arg), self._start, self._stop)) + return hash((EXPRSLICE, hash(self.__arg), self.__start, self.__stop)) def _exprrepr(self): - return "%s(%r, %d, %d)" % (self.__class__.__name__, self._arg, - self._start, self._stop) + return "%s(%r, %d, %d)" % (self.__class__.__name__, self.__arg, + self.__start, self.__stop) def __contains__(self, expr): if self == expr: @@ -990,39 +975,39 @@ class ExprSlice(Expr): @visit_chk def visit(self, cb, tv=None): - arg = self._arg.visit(cb, tv) - if arg == self._arg: + arg = self.__arg.visit(cb, tv) + if arg == self.__arg: return self - return ExprSlice(arg, self._start, self._stop) + return ExprSlice(arg, self.__start, self.__stop) def copy(self): - return ExprSlice(self._arg.copy(), self._start, self._stop) + return ExprSlice(self.__arg.copy(), self.__start, self.__stop) def depth(self): - return self._arg.depth() + 1 + return self.__arg.depth() + 1 def slice_rest(self): "Return the completion of the current slice" - size = self._arg.size - if self._start >= size or self._stop > size: + size = self.__arg.size + if self.__start >= size or self.__stop > size: raise ValueError('bad slice rest %s %s %s' % - (size, self._start, self._stop)) + (size, self.__start, self.__stop)) - if self._start == self._stop: + if self.__start == self.__stop: return [(0, size)] rest = [] - if self._start != 0: - rest.append((0, self._start)) - if self._stop < size: - rest.append((self._stop, size)) + if self.__start != 0: + rest.append((0, self.__start)) + if self.__stop < size: + rest.append((self.__stop, size)) return rest def graph_recursive(self, graph): graph.add_node(self) - self._arg.graph_recursive(graph) - graph.add_uniq_edge(self, self._arg) + self.__arg.graph_recursive(graph) + graph.add_uniq_edge(self, self.__arg) class ExprCompose(Expr): @@ -1037,7 +1022,6 @@ class ExprCompose(Expr): In the example, salad.size == 3. """ - __slots__ = ["_args"] def __init__(self, args): """Create an ExprCompose @@ -1098,7 +1082,7 @@ class ExprCompose(Expr): def __contains__(self, e): if self == e: return True - for arg in self._args: + for arg in self.__args: if arg == e: return True if arg[0].__contains__(e): @@ -1107,18 +1091,18 @@ class ExprCompose(Expr): @visit_chk def visit(self, cb, tv=None): - args = [(arg[0].visit(cb, tv), arg[1], arg[2]) for arg in self._args] - modified = any([arg[0] != arg[1] for arg in zip(self._args, args)]) + args = [(arg[0].visit(cb, tv), arg[1], arg[2]) for arg in self.__args] + modified = any([arg[0] != arg[1] for arg in zip(self.__args, args)]) if modified: return ExprCompose(args) return self def copy(self): - args = [(arg[0].copy(), arg[1], arg[2]) for arg in self._args] + args = [(arg[0].copy(), arg[1], arg[2]) for arg in self.__args] return ExprCompose(args) def depth(self): - depth = [arg[0].depth() for arg in self._args] + depth = [arg[0].depth() for arg in self.__args] return max(depth) + 1 def graph_recursive(self, graph): diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py index 3b85d720..178ee25f 100644 --- a/miasm2/expression/expression_helper.py +++ b/miasm2/expression/expression_helper.py @@ -210,9 +210,6 @@ class Variables_Identifier(object): - original expression with variables translated """ - # Attribute used to distinguish created variables from original ones - is_var_ident = "is_var_ident" - def __init__(self, expr, var_prefix="v"): """Set the expression @expr to handle and launch variable identification process @@ -287,13 +284,11 @@ class Variables_Identifier(object): for element_done in done: todo.remove(element_done) - @classmethod - def is_var_identifier(cls, expr): + def is_var_identifier(self, expr): "Return True iff @expr is a variable identifier" if not isinstance(expr, m2_expr.ExprId): return False - - return expr.is_var_ident + return expr in self._vars def find_variables_rec(self, expr): """Recursive method called by find_variable to expand @expr. @@ -310,7 +305,6 @@ class Variables_Identifier(object): identifier = m2_expr.ExprId("%s%s" % (self.var_prefix, self.var_indice.next()), size = expr.size) - identifier.is_var_ident = True self._vars[identifier] = expr # Recursion stop case diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py index 2aa853f0..70fda11c 100644 --- a/miasm2/ir/analysis.py +++ b/miasm2/ir/analysis.py @@ -283,11 +283,8 @@ class ira(ir): def gen_equations(self): for irb in self.blocs.values(): - symbols_init = {} - for r in self.arch.regs.all_regs_ids: - x = ExprId(r.name, r.size) - x.is_term = True - symbols_init[r] = x + symbols_init = dict(self.arch.regs.all_regs_ids_init) + sb = symbexec(self, dict(symbols_init)) sb.emulbloc(irb) eqs = [] diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py index 1dc8dde1..d3c56f70 100644 --- a/miasm2/ir/symbexec.py +++ b/miasm2/ir/symbexec.py @@ -3,6 +3,8 @@ from miasm2.expression.modint import int32 from miasm2.expression.simplifications import expr_simp from miasm2.core import asmbloc from miasm2.ir.ir import AssignBlock +from miasm2.core.interval import interval + import logging @@ -13,72 +15,82 @@ log.addHandler(console_handler) log.setLevel(logging.INFO) -class symbols(): +class symbols(object): def __init__(self, init=None): if init is None: init = {} self.symbols_id = {} self.symbols_mem = {} - for k, v in init.items(): - self[k] = v + for expr, value in init.items(): + self[expr] = value - def __contains__(self, a): - if not isinstance(a, m2_expr.ExprMem): - return self.symbols_id.__contains__(a) - if not self.symbols_mem.__contains__(a.arg): + def __contains__(self, expr): + if not isinstance(expr, m2_expr.ExprMem): + return self.symbols_id.__contains__(expr) + if not self.symbols_mem.__contains__(expr.arg): return False - return self.symbols_mem[a.arg][0].size == a.size - - def __getitem__(self, a): - if not isinstance(a, m2_expr.ExprMem): - return self.symbols_id.__getitem__(a) - if not a.arg in self.symbols_mem: - raise KeyError(a) - m = self.symbols_mem.__getitem__(a.arg) - if m[0].size != a.size: - raise KeyError(a) - return m[1] - - def __setitem__(self, a, v): - if not isinstance(a, m2_expr.ExprMem): - self.symbols_id.__setitem__(a, v) + return self.symbols_mem[expr.arg][0].size == expr.size + + def __getitem__(self, expr): + if not isinstance(expr, m2_expr.ExprMem): + return self.symbols_id.__getitem__(expr) + if not expr.arg in self.symbols_mem: + raise KeyError(expr) + mem, value = self.symbols_mem.__getitem__(expr.arg) + if mem.size != expr.size: + raise KeyError(expr) + return value + + def get(self, expr, default=None): + if not isinstance(expr, m2_expr.ExprMem): + return self.symbols_id.get(expr, default) + if not expr.arg in self.symbols_mem: + return default + mem, value = self.symbols_mem.__getitem__(expr.arg) + if mem.size != expr.size: + return default + return value + + def __setitem__(self, expr, value): + if not isinstance(expr, m2_expr.ExprMem): + self.symbols_id.__setitem__(expr, value) return - self.symbols_mem.__setitem__(a.arg, (a, v)) + assert expr.size == value.size + self.symbols_mem.__setitem__(expr.arg, (expr, value)) def __iter__(self): - for a in self.symbols_id: - yield a - for a in self.symbols_mem: - yield self.symbols_mem[a][0] - - def __delitem__(self, a): - if not isinstance(a, m2_expr.ExprMem): - self.symbols_id.__delitem__(a) + for expr in self.symbols_id: + yield expr + for expr in self.symbols_mem: + yield self.symbols_mem[expr][0] + + def __delitem__(self, expr): + if not isinstance(expr, m2_expr.ExprMem): + self.symbols_id.__delitem__(expr) else: - self.symbols_mem.__delitem__(a.arg) + self.symbols_mem.__delitem__(expr.arg) def items(self): - k = self.symbols_id.items() + [x for x in self.symbols_mem.values()] - return k + return self.symbols_id.items() + [x for x in self.symbols_mem.values()] def keys(self): - k = self.symbols_id.keys() + [x[0] for x in self.symbols_mem.values()] - return k + return (self.symbols_id.keys() + + [x[0] for x in self.symbols_mem.values()]) def copy(self): - p = symbols() - p.symbols_id = dict(self.symbols_id) - p.symbols_mem = dict(self.symbols_mem) - return p + new_symbols = symbols() + new_symbols.symbols_id = dict(self.symbols_id) + new_symbols.symbols_mem = dict(self.symbols_mem) + return new_symbols def inject_info(self, info): - s = symbols() - for k, v in self.items(): - k = expr_simp(k.replace_expr(info)) - v = expr_simp(v.replace_expr(info)) - s[k] = v - return s + new_symbols = symbols() + for expr, value in self.items(): + expr = expr_simp(expr.replace_expr(info)) + value = expr_simp(value.replace_expr(info)) + new_symbols[expr] = value + return new_symbols class symbexec(object): @@ -88,154 +100,152 @@ class symbexec(object): func_write=None, sb_expr_simp=expr_simp): self.symbols = symbols() - for k, v in known_symbols.items(): - self.symbols[k] = v + for expr, value in known_symbols.items(): + self.symbols[expr] = value self.func_read = func_read self.func_write = func_write self.ir_arch = ir_arch self.expr_simp = sb_expr_simp - def find_mem_by_addr(self, e): - if e in self.symbols.symbols_mem: - return self.symbols.symbols_mem[e][0] + def find_mem_by_addr(self, expr): + """ + Return memory keys with pointer equal to @expr + @expr: address of the searched memory variable + """ + if expr in self.symbols.symbols_mem: + return self.symbols.symbols_mem[expr][0] return None - def eval_ExprId(self, e, eval_cache=None): - if eval_cache is None: - eval_cache = {} - if isinstance(e.name, asmbloc.asm_label) and e.name.offset is not None: - return m2_expr.ExprInt_from(e, e.name.offset) - if not e in self.symbols: - # raise ValueError('unknown symbol %s'% e) - return e - return self.symbols[e] - - def eval_ExprInt(self, e, eval_cache=None): - return e - - 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) + 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]) + tmp = m2_expr.ExprSlice(m2_expr.ExprCompose(out), 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: - # XXX hack test - a.is_term = True - return a + return expr # bigger lookup - if a.size > tmp.size: - rest = a.size - ptr = a_val + if size > ret.size: + rest = size + ptr = ptr 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 + mem = self.find_mem_by_addr(ptr) + if mem is None: + value = m2_expr.ExprMem(ptr, 8) + mem = value diff_size = 8 - elif rest >= v.size: - val = self.symbols[v] - diff_size = v.size + elif rest >= mem.size: + value = self.symbols[mem] + diff_size = mem.size else: diff_size = rest - val = self.symbols[v][0:diff_size] - val = (val, ptr_index, ptr_index + diff_size) - out.append(val) + 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( - 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 + 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 - tmp = self.expr_simp(m2_expr.ExprSlice(self.symbols[tmp], 0, a.size)) - return tmp - - def eval_expr_visit(self, e, eval_cache=None): - if eval_cache is None: - eval_cache = {} - # print 'visit', e, e.is_term - if e.is_term: - return e - if e in eval_cache: - return eval_cache[e] - c = e.__class__ - deal_class = {m2_expr.ExprId: self.eval_ExprId, - m2_expr.ExprInt: self.eval_ExprInt, - m2_expr.ExprMem: self.eval_ExprMem, - } - # print 'eval', e - if c in deal_class: - e = deal_class[c](e, eval_cache) - # print "ret", e - if not (isinstance(e, m2_expr.ExprId) or isinstance(e, - m2_expr.ExprInt)): - e.is_term = True - return e - - def eval_expr(self, e, eval_cache=None): - if eval_cache is None: - eval_cache = {} - r = e.visit(lambda x: self.eval_expr_visit(x, eval_cache)) - return r + ret = self.expr_simp(self.symbols[ret][:size]) + return ret + + + def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0): + """ + Deep First evaluate nodes: + 1. evaluate node's sons + 2. simplify + """ + + #print '\t'*level, "Eval:", expr + if expr in cache: + ret = cache[expr] + #print "In cache!", ret + elif isinstance(expr, m2_expr.ExprInt): + return expr + elif isinstance(expr, m2_expr.ExprId): + if isinstance(expr.name, asmbloc.asm_label) and expr.name.offset is not None: + ret = m2_expr.ExprInt_from(expr, expr.name.offset) + else: + ret = state.get(expr, expr) + elif isinstance(expr, m2_expr.ExprMem): + 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 isinstance(expr, m2_expr.ExprCond): + 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 isinstance(expr, m2_expr.ExprSlice): + arg = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) + ret = m2_expr.ExprSlice(arg, expr.start, expr.stop) + elif isinstance(expr, m2_expr.ExprOp): + 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 isinstance(expr, m2_expr.ExprCompose): + args = [] + for (arg, start, stop) in expr.args: + arg = self.apply_expr_on_state_visit_cache(arg, state, cache, level+1) + args.append((arg, start, stop)) + 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 apply_expr_on_state(self, expr, cache): + if cache is None: + cache = {} + ret = self.apply_expr_on_state_visit_cache(expr, self.symbols, cache) + return ret + + def eval_expr(self, expr, eval_cache=None): + return self.apply_expr_on_state(expr, eval_cache) def modified_regs(self, init_state=None): if init_state is None: @@ -250,121 +260,111 @@ class symbexec(object): yield i def modified_mems(self, init_state=None): + if init_state is None: + init_state = self.ir_arch.arch.regs.regs_init mems = self.symbols.symbols_mem.values() mems.sort() - for m, _ in mems: - yield m + for mem, _ in mems: + if mem in init_state and \ + mem in self.symbols.symbols_mem and \ + self.symbols.symbols_mem[mem] == init_state[mem]: + continue + yield mem def modified(self, init_state=None): - for r in self.modified_regs(init_state): - yield r - for m in self.modified_mems(init_state): - yield m + for reg in self.modified_regs(init_state): + yield reg + for mem in self.modified_mems(init_state): + yield mem def dump_id(self): + """ + Dump modififed registers symbols only + """ ids = self.symbols.symbols_id.keys() ids.sort() - for i in ids: - if i in self.ir_arch.arch.regs.regs_init and \ - i in self.symbols.symbols_id and \ - self.symbols.symbols_id[i] == self.ir_arch.arch.regs.regs_init[i]: + for expr in ids: + if (expr in self.ir_arch.arch.regs.regs_init and + expr in self.symbols.symbols_id and + self.symbols.symbols_id[expr] == self.ir_arch.arch.regs.regs_init[expr]): continue - print i, self.symbols.symbols_id[i] + print expr, "=", self.symbols.symbols_id[expr] def dump_mem(self): + """ + Dump modififed memory symbols + """ mems = self.symbols.symbols_mem.values() mems.sort() - for m, v in mems: - print m, v + for mem, value in mems: + print mem, value def rest_slice(self, slices, start, stop): - o = [] + """ + Return the complementary slices of @slices in the range @start, @stop + @slices: base slices + @start, @stop: interval range + """ + out = [] last = start - for _, a, b in slices: - if a == last: - last = b + for _, slice_start, slice_stop in slices: + if slice_start == last: + last = slice_stop continue - o.append((last, a)) - last = b + out.append((last, slice_start)) + last = slice_stop if last != stop: - o.append((b, stop)) - return o - - def substract_mems(self, a, b): - ex = b.arg - a.arg - ex = self.expr_simp(self.eval_expr(ex, {})) - if not isinstance(ex, m2_expr.ExprInt): - return None - ptr_diff = int(int32(ex.arg)) - out = [] - if ptr_diff < 0: - # [a ] - #[b ]XXX - sub_size = b.size + ptr_diff * 8 - if sub_size >= a.size: - pass - else: - ex = m2_expr.ExprOp('+', a.arg, - m2_expr.ExprInt_from(a.arg, sub_size / 8)) - ex = self.expr_simp(self.eval_expr(ex, {})) + out.append((slice_stop, stop)) + return out - rest_ptr = ex - rest_size = a.size - sub_size + def substract_mems(self, arg1, arg2): + """ + Return the remaining memory areas of @arg1 - @arg2 + @arg1, @arg2: ExprMem + """ - val = self.symbols[a][sub_size:a.size] - out = [(m2_expr.ExprMem(rest_ptr, rest_size), val)] - else: - #[a ] - # XXXX[b ]YY + ptr_diff = self.expr_simp(arg2.arg - arg1.arg) + ptr_diff = int(int32(ptr_diff.arg)) - #[a ] - # XXXX[b ] + zone1 = interval([(0, arg1.size/8-1)]) + zone2 = interval([(ptr_diff, ptr_diff + arg2.size/8-1)]) + zones = zone1 - zone2 + + out = [] + for start, stop in zones: + ptr = arg1.arg + m2_expr.ExprInt(start, arg1.arg.size) + ptr = self.expr_simp(ptr) + value = self.expr_simp(self.symbols[arg1][start*8:(stop+1)*8]) + mem = m2_expr.ExprMem(ptr, (stop - start + 1)*8) + assert mem.size == value.size + out.append((mem, value)) - out = [] - # part X - if ptr_diff > 0: - val = self.symbols[a][0:ptr_diff * 8] - out.append((m2_expr.ExprMem(a.arg, ptr_diff * 8), val)) - # part Y - if ptr_diff * 8 + b.size < a.size: - - ex = m2_expr.ExprOp('+', b.arg, - m2_expr.ExprInt_from(b.arg, b.size / 8)) - ex = self.expr_simp(self.eval_expr(ex, {})) - - rest_ptr = ex - rest_size = a.size - (ptr_diff * 8 + b.size) - val = self.symbols[a][ptr_diff * 8 + b.size:a.size] - out.append((m2_expr.ExprMem(ex, val.size), val)) return out - # give mem stored overlapping requested mem ptr - def get_mem_overlapping(self, e, eval_cache=None): - if eval_cache is None: - eval_cache = {} - if not isinstance(e, m2_expr.ExprMem): - raise ValueError('mem overlap bad arg') - ov = [] - # suppose max mem size is 64 bytes, compute all reachable addresses - to_test = [] - base_ptr = self.expr_simp(e.arg) - for i in xrange(-7, e.size / 8): - ex = self.expr_simp( - self.eval_expr(base_ptr + m2_expr.ExprInt_from(e.arg, i), - eval_cache)) - to_test.append((i, ex)) - - for i, x in to_test: - if not x in self.symbols.symbols_mem: + + def get_mem_overlapping(self, expr): + """ + Gives mem stored overlapping memory in @expr + Hypothesis: Max mem size is 64 bytes, compute all reachable addresses + @expr: target memory + """ + + overlaps = [] + base_ptr = self.expr_simp(expr.arg) + for i in xrange(-7, expr.size / 8): + new_ptr = base_ptr + m2_expr.ExprInt(i, expr.arg.size) + new_ptr = self.expr_simp(new_ptr) + + mem, origin = self.symbols.symbols_mem.get(new_ptr, (None, None)) + if mem is None: continue - ex = self.expr_simp(self.eval_expr(e.arg - x, eval_cache)) - if not isinstance(ex, m2_expr.ExprInt): - raise ValueError('ex is not ExprInt') - ptr_diff = int32(ex.arg) - if ptr_diff >= self.symbols.symbols_mem[x][1].size / 8: - # print "too long!" + + ptr_diff = -i + if ptr_diff >= origin.size / 8: + # access is too small to overlap the memory target continue - ov.append((i, self.symbols.symbols_mem[x][0])) - return ov + overlaps.append((i, mem)) + + return overlaps def eval_ir_expr(self, assignblk): """ @@ -372,16 +372,14 @@ class symbexec(object): @assignblk: AssignBlock instance """ pool_out = {} - - eval_cache = dict(self.symbols.items()) + eval_cache = {} for dst, src in assignblk.iteritems(): src = self.eval_expr(src, eval_cache) if isinstance(dst, m2_expr.ExprMem): - a = self.eval_expr(dst.arg, eval_cache) - a = self.expr_simp(a) + ptr = self.eval_expr(dst.arg, eval_cache) # test if mem lookup is known - tmp = m2_expr.ExprMem(a, dst.size) + tmp = m2_expr.ExprMem(ptr, dst.size) pool_out[tmp] = src elif isinstance(dst, m2_expr.ExprId): @@ -398,18 +396,18 @@ class symbexec(object): """ mem_dst = [] src_dst = self.eval_ir_expr(assignblk) - eval_cache = dict(self.symbols.items()) for dst, src in src_dst: if isinstance(dst, m2_expr.ExprMem): - mem_overlap = self.get_mem_overlapping(dst, eval_cache) + mem_overlap = self.get_mem_overlapping(dst) for _, base in mem_overlap: diff_mem = self.substract_mems(base, dst) del self.symbols[base] for new_mem, new_val in diff_mem: - new_val.is_term = True self.symbols[new_mem] = new_val src_o = self.expr_simp(src) self.symbols[dst] = src_o + if dst == src_o: + del self.symbols[dst] if isinstance(dst, m2_expr.ExprMem): if self.func_write and isinstance(dst.arg, m2_expr.ExprInt): self.func_write(self, dst, src_o) @@ -424,51 +422,52 @@ class symbexec(object): @step: display intermediate steps """ for assignblk in irb.irs: - self.eval_ir(assignblk) if step: + print 'Assignblk:' + print assignblk print '_' * 80 + self.eval_ir(assignblk) + if step: self.dump_id() - eval_cache = dict(self.symbols.items()) - return self.eval_expr(self.ir_arch.IRDst, eval_cache) + self.dump_mem() + print '_' * 80 + return self.eval_expr(self.ir_arch.IRDst) - def emul_ir_bloc(self, myir, ad, step=False): - b = myir.get_bloc(ad) - if b is not None: - ad = self.emulbloc(b, step=step) - return ad + def emul_ir_bloc(self, myir, addr, step=False): + irblock = myir.get_bloc(addr) + if irblock is not None: + addr = self.emulbloc(irblock, step=step) + return addr - def emul_ir_blocs(self, myir, ad, lbl_stop=None, step=False): + def emul_ir_blocs(self, myir, addr, lbl_stop=None, step=False): while True: - b = myir.get_bloc(ad) - if b is None: + irblock = myir.get_bloc(addr) + if irblock is None: break - if b.label == lbl_stop: + if irblock.label == lbl_stop: break - ad = self.emulbloc(b, step=step) - return ad - - def del_mem_above_stack(self, sp): - sp_val = self.symbols[sp] - for mem_ad, (mem, _) in self.symbols.symbols_mem.items(): - # print mem_ad, sp_val - diff = self.eval_expr(mem_ad - sp_val, {}) - diff = expr_simp(diff) + addr = self.emulbloc(irblock, step=step) + return addr + + def del_mem_above_stack(self, stack_ptr): + stack_ptr = self.eval_expr(stack_ptr) + for mem_addr, (mem, _) in self.symbols.symbols_mem.items(): + diff = self.expr_simp(mem_addr - stack_ptr) if not isinstance(diff, m2_expr.ExprInt): continue - m = expr_simp(diff.msb()) - if m.arg == 1: + sign_bit = self.expr_simp(diff.msb()) + if sign_bit.arg == 1: del self.symbols[mem] def apply_expr(self, expr): """Evaluate @expr and apply side effect if needed (ie. if expr is an assignment). Return the evaluated value""" - # Eval expression - to_eval = expr.src if isinstance(expr, m2_expr.ExprAff) else expr - ret = self.expr_simp(self.eval_expr(to_eval)) - # Update value if needed if isinstance(expr, m2_expr.ExprAff): - self.eval_ir(AssignBlock([m2_expr.ExprAff(expr.dst, ret)])) + ret = self.eval_expr(expr.src) + self.eval_ir(AssignBlock([expr])) + else: + ret = self.eval_expr(expr) return ret diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py index 9165fccb..19cc47db 100644 --- a/test/ir/symbexec.py +++ b/test/ir/symbexec.py @@ -21,7 +21,7 @@ class TestSymbExec(unittest.TestCase): addr40 = ExprInt32(40) addr50 = ExprInt32(50) mem0 = ExprMem(addr0) - mem1 = ExprMem(addr1) + mem1 = ExprMem(addr1, 8) mem8 = ExprMem(addr8) mem9 = ExprMem(addr9) mem20 = ExprMem(addr20) @@ -34,22 +34,24 @@ class TestSymbExec(unittest.TestCase): id_a = ExprId('a') id_eax = ExprId('eax_init') - e = symbexec( - ir_x86_32(), {mem0: id_x, mem1: id_y, mem9: id_x, mem40w: id_x, mem50v: id_y, id_a: addr0, id_eax: addr0}) + e = symbexec(ir_x86_32(), + {mem0: id_x, mem1: id_y, mem9: id_x, + mem40w: id_x[:16], mem50v: id_y, + id_a: addr0, id_eax: addr0}) self.assertEqual(e.find_mem_by_addr(addr0), mem0) self.assertEqual(e.find_mem_by_addr(addrX), None) - self.assertEqual(e.eval_ExprMem(ExprMem(addr1 - addr1)), id_x) - self.assertEqual(e.eval_ExprMem(ExprMem(addr1, 8)), id_y) - self.assertEqual(e.eval_ExprMem(ExprMem(addr1 + addr1)), ExprCompose( + self.assertEqual(e.eval_expr(ExprMem(addr1 - addr1)), id_x) + self.assertEqual(e.eval_expr(ExprMem(addr1, 8)), id_y) + self.assertEqual(e.eval_expr(ExprMem(addr1 + addr1)), ExprCompose( [(id_x[16:32], 0, 16), (ExprMem(ExprInt32(4), 16), 16, 32)])) - self.assertEqual(e.eval_ExprMem(mem8), ExprCompose( + self.assertEqual(e.eval_expr(mem8), ExprCompose( [(id_x[0:24], 0, 24), (ExprMem(ExprInt32(11), 8), 24, 32)])) - self.assertEqual(e.eval_ExprMem(mem40v), id_x[:8]) - self.assertEqual(e.eval_ExprMem(mem50w), ExprCompose( + self.assertEqual(e.eval_expr(mem40v), id_x[:8]) + self.assertEqual(e.eval_expr(mem50w), ExprCompose( [(id_y, 0, 8), (ExprMem(ExprInt32(51), 8), 8, 16)])) - self.assertEqual(e.eval_ExprMem(mem20), mem20) + self.assertEqual(e.eval_expr(mem20), mem20) e.func_read = lambda x: x - self.assertEqual(e.eval_ExprMem(mem20), mem20) + self.assertEqual(e.eval_expr(mem20), mem20) self.assertEqual(set(e.modified()), set(e.symbols)) self.assertRaises( KeyError, e.symbols.__getitem__, ExprMem(ExprInt32(100))) |