about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorFabrice Desclaux <fabrice.desclaux@cea.fr>2017-07-22 16:20:10 +0200
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2017-08-07 10:28:02 +0200
commitb2540d10b5e040cb959cc4637fc24ee48a0deb1b (patch)
tree7c1400aed17cbf4b038d3fa4927573c2e7615882
parent7ef509195617482e4e0393c5cbf08ecd3b0e4a1c (diff)
downloadmiasm-b2540d10b5e040cb959cc4637fc24ee48a0deb1b.tar.gz
miasm-b2540d10b5e040cb959cc4637fc24ee48a0deb1b.zip
Objc: support multi accesses/types
-rw-r--r--miasm2/core/objc.py53
-rw-r--r--miasm2/ir/symbexec_types.py68
2 files changed, 66 insertions, 55 deletions
diff --git a/miasm2/core/objc.py b/miasm2/core/objc.py
index a1604d99..de98993b 100644
--- a/miasm2/core/objc.py
+++ b/miasm2/core/objc.py
@@ -744,17 +744,20 @@ class CTypeAnalyzer(ExprReducer):
 
     def reduce_ptr_plus_cst(self, node, lvl):
         """Get type of ptr + CST"""
-
         if not node.expr.is_op("+") or len(node.args) != 2:
             return None
-        args_types = set([self.get_solo_type(node.args[0]),
-                          self.get_solo_type(node.args[1])])
-        if args_types != set([ObjCInt, ObjCPtr]):
+        type_arg1 = self.get_solo_type(node.args[1])
+        if type_arg1 != ObjCInt:
             return None
+
         arg0, arg1 = node.args
+        if arg0.info is None:
+            return None
         out = []
         ptr_offset = int(arg1.expr)
         for info in arg0.info:
+            if not isinstance(info, ObjCPtr):
+                continue
             ptr_basetype = info.objtype
             if ptr_basetype.size == 0:
                 missing_definition(ptr_basetype)
@@ -764,12 +767,10 @@ class CTypeAnalyzer(ExprReducer):
                                    ptr_offset % ptr_basetype.size,
                                    False,
                                    lvl)
-
         return out
 
     def reduce_cst_op_cst(self, node, _):
         """Get type of CST + CST"""
-
         if not node.expr.is_op("+") or len(node.args) != 2:
             return None
         if node.args[0] is None or node.args[1] is None:
@@ -777,7 +778,7 @@ class CTypeAnalyzer(ExprReducer):
         args_types = set([self.get_solo_type(node.args[0]),
                           self.get_solo_type(node.args[1])])
         if args_types != set([ObjCInt]):
-            return None
+            return []
         return [self.CST]
 
     def reduce_deref(self, node, lvl):
@@ -786,7 +787,6 @@ class CTypeAnalyzer(ExprReducer):
         * @64[ptr<ptr<elem>>] -> ptr<elem>
         * @32[ptr<struct>] -> struct.00
         """
-
         if not isinstance(node.expr, ExprMem):
             return None
         if node.arg.info is None:
@@ -795,7 +795,7 @@ class CTypeAnalyzer(ExprReducer):
         for subtype in node.arg.info:
             # subtype : ptr<elem>
             if not isinstance(subtype, (ObjCPtr, ObjCArray)):
-                return None
+                continue
             target = subtype.objtype
             # target : type(elem)
             for ptr_target in self.get_typeof(target, 0, True, lvl):
@@ -806,8 +806,6 @@ class CTypeAnalyzer(ExprReducer):
                     r_target.size != node.expr.size / 8):
                     continue
                 found.append(r_target)
-        if not found:
-            return None
         return found
 
     reduction_rules = [reduce_id, reduce_int,
@@ -818,7 +816,6 @@ class CTypeAnalyzer(ExprReducer):
     def get_type(self, expr):
         """Return the C type(s) of the native Miasm expression @expr
         @expr: Miasm expression"""
-
         return self.reduce(expr)
 
 
@@ -1011,9 +1008,9 @@ class ExprToAccessC(ExprReducer):
                 node.expr.name in self.expr_types):
             return None
 
-        objc = self.expr_types[node.expr.name]
-        out = CGenId(objc, node.expr.name)
-        return [out]
+        objcs = self.expr_types[node.expr.name]
+        out = [CGenId(objc, node.expr.name) for objc in objcs]
+        return out
 
     def reduce_int(self, node, _):
         """Generate access for ExprInt"""
@@ -1032,26 +1029,25 @@ class ExprToAccessC(ExprReducer):
 
     def reduce_op(self, node, lvl):
         """Generate access for ExprOp"""
-
         if not node.expr.is_op("+") or len(node.args) != 2:
             return None
-        args_types = set([self.get_solo_type(node.args[0]),
-                          self.get_solo_type(node.args[1])])
-        if args_types != set([ObjCInt, ObjCPtr]):
+        type_arg1 = self.get_solo_type(node.args[1])
+        if type_arg1 != ObjCInt:
             return None
-
         arg0, arg1 = node.args
+        if arg0.info is None:
+            return None
         out = []
         ptr_offset = int(arg1.expr)
-        for name in arg0.info:
-            assert isinstance(name.ctype, ObjCPtr)
-            ptr_basetype = name.ctype.objtype
+        for info in arg0.info:
+            if not isinstance(info.ctype, ObjCPtr):
+                continue
+            ptr_basetype = info.ctype.objtype
             # Array-like: int* ptr; ptr[1] = X
-            ret = self.cgen_access(name,
+            ret = self.cgen_access(info,
                                    ptr_basetype,
                                    ptr_offset, False, lvl)
-            for subcgenobj in ret:
-                out.append(subcgenobj)
+            out += ret
         return out
 
     def reduce_mem(self, node, lvl):
@@ -1063,6 +1059,11 @@ class ExprToAccessC(ExprReducer):
 
         if not isinstance(node.expr, ExprMem):
             return None
+        if node.expr in self.expr_types:
+            objcs = self.expr_types[node.expr]
+            out = [CGenId(objc, str(node.expr)) for objc in objcs]
+            return out
+
         if node.arg.info is None:
             return None
         assert isinstance(node.arg.info, list)
diff --git a/miasm2/ir/symbexec_types.py b/miasm2/ir/symbexec_types.py
index 2a99148f..bc5546de 100644
--- a/miasm2/ir/symbexec_types.py
+++ b/miasm2/ir/symbexec_types.py
@@ -111,6 +111,12 @@ class SymbExecCType(SymbolicExecutionEngine):
         return objc
 
     def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0):
+        ret = self._apply_expr_on_state_visit_cache(expr, state, cache, level)
+        if not ret:
+            return None
+        return tuple(ret)
+
+    def _apply_expr_on_state_visit_cache(self, expr, state, cache, level=0):
         """
         Deep First evaluate nodes:
             1. evaluate node's sons
@@ -118,56 +124,58 @@ class SymbExecCType(SymbolicExecutionEngine):
         """
 
         expr = self.expr_simp(expr)
-
         if expr in cache:
             return cache[expr]
+        elif expr in self.symbols:
+            ret =  self.symbols[expr]
+            return ret
         elif expr in state:
             return state[expr]
         elif isinstance(expr, ExprInt):
             objc = self.get_type_int_by_size(expr.size)
             if objc is None:
                 objc = self.chandler.type_analyzer.types_mngr.get_objc(CTypeId('int'))
-            return objc
+            return [objc]
         elif isinstance(expr, ExprId):
             if expr in state:
                 return state[expr]
             return None
         elif isinstance(expr, ExprMem):
-            ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level + 1)
-            if ptr is None:
-                return None
-            self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = ptr
+            ptr_type = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level + 1)
+            if not ptr_type:
+                return ptr_type
+            self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = ptr_type
             ptr_expr = ExprId(self.OBJC_INTERNAL, expr.arg.size)
             objcs = self.chandler.expr_to_types(ExprMem(ptr_expr, expr.size))
-            if objcs is None:
-                return None
-            objc = objcs[0]
-            return objc
+            return objcs
         elif isinstance(expr, ExprCond):
             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)
-            types = [src1, src2]
-            objc = self.is_offset_list(types, expr.size)
-            if objc:
-                return objc
-            return None
+            if src1 is None or src2 is None:
+                return None
+            # Return common types
+            types = list(set(src1).intersection(src2))
+            return types
         elif isinstance(expr, ExprSlice):
             objc = self.get_type_int_by_size(expr.size)
             if objc is None:
-                # default size
-                objc = self.offset_types[0]
-            return objc
+                return None
+            return [objc]
         elif isinstance(expr, ExprOp):
+            if expr.op.startswith("call"):
+                return None
             args = []
             types = []
             for oarg in expr.args:
-                arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1)
-                types.append(arg)
+                arg_types = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1)
+                if arg_types is None:
+                    return None
+                types += list(arg_types)
             if None in types:
                 return None
             objc = self.is_offset_list(types, expr.size)
             if objc:
-                return objc
+                return [objc]
             # Find Base + int
             if expr.op != '+':
                 return None
@@ -176,21 +184,23 @@ class SymbExecCType(SymbolicExecutionEngine):
                 offset = args.pop()
                 types.pop()
             if len(args) == 1:
-                arg, arg_type = args.pop(), types.pop()
-                self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = arg_type
+                arg, arg_types = args.pop(), types
+                self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = arg_types
                 ptr_expr = ExprId(self.OBJC_INTERNAL, arg.size)
-                objc = self.chandler.expr_to_types(ptr_expr + offset)
-                objc = objc[0]
-                return objc
+                objcs = self.chandler.expr_to_types(ptr_expr + offset)
+                return objcs
             return None
         elif isinstance(expr, ExprCompose):
             types = set()
             for oarg in expr.args:
-                arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1)
-                types.add(arg)
+                arg_types = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1)
+                if arg_types is None:
+                    return None
+                types.update(arg_types)
             objc = self.is_offset_list(types, expr.size)
             if objc:
-                return objc
+                return [objc]
+
             return None
         else:
             raise TypeError("Unknown expr type")