about summary refs log tree commit diff stats
path: root/miasm/expression/expression.py
diff options
context:
space:
mode:
authorserpilliere <devnull@localhost>2012-02-23 11:19:51 +0100
committerserpilliere <devnull@localhost>2012-02-23 11:19:51 +0100
commitb740368c1d7227c7fbdc51743aaa7cdf2b0b8965 (patch)
treef0561ba893fc241549521cbc951996bfbaa6db0f /miasm/expression/expression.py
parent2edcf899f6c403dce2295c38703ae8af3040feb0 (diff)
downloadfocaccia-miasm-b740368c1d7227c7fbdc51743aaa7cdf2b0b8965.tar.gz
focaccia-miasm-b740368c1d7227c7fbdc51743aaa7cdf2b0b8965.zip
add expr canonization form
Diffstat (limited to 'miasm/expression/expression.py')
-rw-r--r--miasm/expression/expression.py115
1 files changed, 107 insertions, 8 deletions
diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py
index ae8b415b..25aabb0e 100644
--- a/miasm/expression/expression.py
+++ b/miasm/expression/expression.py
@@ -172,7 +172,8 @@ class ExprInt(Expr):
 
     def toC(self):
         return str(self)
-
+    def canonize(self):
+        return self
 
 class ExprId(Expr):
     def __init__(self, name, size = 32, is_term = False):
@@ -213,6 +214,8 @@ class ExprId(Expr):
 
     def toC(self):
         return str(self)
+    def canonize(self):
+        return self
 
 memreg = ExprId('MEM')
 
@@ -285,6 +288,8 @@ class ExprAff(Expr):
                 modified_s.append(x)
 
         return modified_s
+    def canonize(self):
+        return ExprAff(self.src.canonize(), self.dst.canonize())
 
 
 class ExprCond(Expr):
@@ -333,6 +338,10 @@ class ExprCond(Expr):
 
     def toC(self):
         return "(%s?%s:%s)"%(self.cond.toC(), self.src1.toC(), self.src2.toC())
+    def canonize(self):
+        return ExprAff(self.cond.canonize(),
+                       self.src1.canonize(),
+                       self.src2.canonize())
 
 class ExprMem(Expr):
     def __init__(self, arg, size = 32, segm = None):
@@ -384,6 +393,8 @@ class ExprMem(Expr):
             return "MEM_LOOKUP_%.2d_SEGM(%s, %s)"%(self.size, self.segm.toC(), self.arg.toC())
         else:
             return "MEM_LOOKUP_%.2d(%s)"%(self.size, self.arg.toC())
+    def canonize(self):
+        return ExprMem(self.arg.canonize(), size = self.size)
 
 class ExprOp(Expr):
     def __init__(self, op, *args):
@@ -572,23 +583,25 @@ class ExprOp(Expr):
                       '<<<c_cf':'rcl_cf_op',
                       '>>>c_rez':'rcr_rez_op',
                       '>>>c_cf':'rcr_cf_op',
-                      
                       }
             if not self.op in dct_div:
                 fsdff
 
             return '(%s(%s, %s, %s, %s) &0x%x)'%(dct_div[self.op],
                                                  self.args[0].get_size(),
-                                                 self.args[0].toC(), 
+                                                 self.args[0].toC(),
                                                  self.args[1].toC(),
                                                  self.args[2].toC(),
                                                  my_size_mask[self.args[0].get_size()])
         else:
-            
             raise ValueError('not imple', str(self))
-        
+    def canonize(self):
+        args = [x.canonize() for x in self.args]
+        if self.op in ['+', '^', '&', '|', '*']:
+            args = canonize_expr_list(args)
+        return ExprOp(self.op, *args)
+
 
-    
 class ExprSlice(Expr):
     def __init__(self, arg, start, stop):
         self.arg, self.start, self.stop = arg, start, stop
@@ -629,6 +642,10 @@ class ExprSlice(Expr):
     def toC(self):
         # XXX gen mask in python for 64 bit & 32 bit compat
         return "((%s>>%d) & ((0xFFFFFFFF>>(32-%d))))"%(self.arg.toC(), self.start, self.stop-self.start)
+    def canonize(self):
+        return ExprSlice(self.arg.canonize(),
+                         self.start,
+                         self.stop)
 
 
 class ExprSliceTo(Expr):
@@ -668,6 +685,10 @@ class ExprSliceTo(Expr):
     def toC(self):
         # XXX gen mask in python for 64 bit & 32 bit compat
         return "((%s & (0xFFFFFFFF>>(32-%d))) << %d)"%(self.arg.toC(), self.stop-self.start, self.start)
+    def canonize(self):
+        return ExprSliceTo(self.arg.canonize(),
+                           self.start,
+                           self.stop)
 
 class ExprCompose(Expr):
     def __init__(self, args):
@@ -725,8 +746,9 @@ class ExprCompose(Expr):
     def toC(self):
         out = ' | '.join([x.toC() for x in self.args])
         return '('+out+')'
-        
-                       
+    def canonize(self):
+        return ExprCompose(canonize_expr_list([x.canonize() for x in self.args]))
+
 class set_expr:
     def __init__(self, l = []):
         self._list = []
@@ -778,3 +800,80 @@ class set_expr:
 
     def __iter__(self):
         return self._list.__iter__()
+
+
+expr_order_dict = {ExprId: 1,
+                   ExprCond: 2,
+                   ExprMem: 3,
+                   ExprOp: 4,
+                   ExprSlice: 5,
+                   ExprSliceTo: 6,
+                   ExprCompose: 7,
+                   ExprInt: 8,
+                   }
+
+def compare_exprs_list(l1_e, l2_e):
+    for i in xrange(min(len(l1_e, l2_e))):
+        x = expr_compare(l1_e[i], l2_e[i])
+        if x: return x
+    return cmp(len(l1_e), len(l2_e))
+
+# compare 2 expressions for canonization
+# 0  => ==
+# 1  => e1 > e2
+# -1 => e1 < e2
+def compare_exprs(e1, e2):
+    c1 = e1.__class__
+    c2 = e2.__class__
+
+    if c1 != c2:
+        return cmp(expr_order_dict[c1], expr_order_dict[c2])
+    if e1 == e2:
+        return 0
+    if c1 == ExprInt:
+        return cmp(e1.arg, e2.arg)
+    elif c1 == ExprId:
+        x = cmp(e1.name, e2.name)
+        if x: return x
+        return cmp(e1.size, e2.size)
+    elif c1 == ExprAff:
+        fds
+    elif c2 == ExprCond:
+        x = compare_exprs(e1.cond, e2.cond)
+        if x: return x
+        x = compare_exprs(e1.src1, e2.src1)
+        if x: return x
+        x = compare_exprs(e1.src2, e2.src2)
+        return x
+    elif c1 == ExprMem:
+        x = compare_exprs(e1.arg, e2.arg)
+        if x: return x
+        return cmp(e1.size, e2.size)
+    elif c1 == ExprOp:
+        if e1.op != e2.op:
+            return cmp(e1.op, e2.op)
+        return compare_exprs_list(e1.arg, e2.arg)
+    elif c1 == ExprSlice:
+        x = compare_exprs(e1.arg, e2.arg)
+        if x: return x
+        x = cmp(e1.start, e2.start)
+        if x: return x
+        x = cmp(e1.stop, e2.stop)
+        return x
+    elif c1 == ExprSliceTo:
+        x = compare_exprs(e1.arg, e2.arg)
+        if x: return x
+        x = cmp(e1.start, e2.start)
+        if x: return x
+        x = cmp(e1.stop, e2.stop)
+        return x
+    elif c1 == ExprCompose:
+        return compare_exprs_list(e1.arg, e2.arg)
+    raise ValueError("not imppl %r %r"%(e1, e2))
+
+
+
+def canonize_expr_list(l):
+    l = l[:]
+    l.sort(cmp=compare_exprs)
+    return l