about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/analysis/dse.py36
-rw-r--r--miasm2/arch/ppc/arch.py8
-rw-r--r--miasm2/arch/ppc/sem.py23
3 files changed, 42 insertions, 25 deletions
diff --git a/miasm2/analysis/dse.py b/miasm2/analysis/dse.py
index d97897d8..38c9aeaf 100644
--- a/miasm2/analysis/dse.py
+++ b/miasm2/analysis/dse.py
@@ -484,6 +484,7 @@ class DSEPathConstraint(DSEEngine):
         self._known_solutions = set() # set of solution identifiers
         self.z3_trans = Translator.to_language("z3")
         self._produce_solution_strategy = produce_solution
+        self._previous_addr = None
         self._history = None
         if produce_solution == self.PRODUCE_SOLUTION_PATH_COV:
             self._history = [] # List of addresses in the current path
@@ -493,6 +494,10 @@ class DSEPathConstraint(DSEEngine):
         snap["new_solutions"] = {dst: src.copy
                                  for dst, src in self.new_solutions.iteritems()}
         snap["cur_constraints"] = self.cur_solver.assertions()
+        if self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV:
+            snap["_history"] = list(self._history)
+        elif self._produce_solution_strategy == self.PRODUCE_SOLUTION_BRANCH_COV:
+            snap["_previous_addr"] = self._previous_addr
         return snap
 
     def restore_snapshot(self, snapshot, keep_known_solutions=True, **kwargs):
@@ -507,6 +512,10 @@ class DSEPathConstraint(DSEEngine):
         self.cur_solver.add(snapshot["cur_constraints"])
         if not keep_known_solutions:
             self._known_solutions.clear()
+        if self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV:
+            self._history = list(snapshot["_history"])
+        elif self._produce_solution_strategy == self.PRODUCE_SOLUTION_BRANCH_COV:
+            self._previous_addr = snapshot["_previous_addr"]
 
     def _key_for_solution_strategy(self, destination):
         """Return the associated identifier for the current solution strategy"""
@@ -521,8 +530,7 @@ class DSEPathConstraint(DSEEngine):
         elif self._produce_solution_strategy == self.PRODUCE_SOLUTION_BRANCH_COV:
             # Decision based on branch coverage
             # -> produce a solution if the current branch has never been take
-            cur_addr = ExprInt(self.jitter.pc, self.ir_arch.IRDst.size)
-            key = (cur_addr, destination)
+            key = (self._previous_addr, destination)
 
         elif self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV:
             # Decision based on path coverage
@@ -553,17 +561,28 @@ class DSEPathConstraint(DSEEngine):
         self.new_solutions[key] = model
         self._known_solutions.add(key)
 
-    def handle(self, cur_addr):
-        # Update history if needed
+    def handle_correct_destination(self, destination, path_constraints):
+        """[DEV] Called by handle() to update internal structures giving the
+        correct destination (the concrete execution one).
+        """
+
+        # Update structure used by produce_solution()
         if self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV:
-            self._history.append(cur_addr)
+            self._history.append(destination)
+        elif self._produce_solution_strategy == self.PRODUCE_SOLUTION_BRANCH_COV:
+            self._previous_addr = destination
+
+        # Update current solver
+        for cons in path_constraints:
+            self.cur_solver.add(self.z3_trans.from_expr(cons))
 
+    def handle(self, cur_addr):
         symb_pc = self.eval_expr(self.ir_arch.IRDst)
         possibilities = possible_values(symb_pc)
+        cur_path_constraint = set() # path_constraint for the concrete path
         if len(possibilities) == 1:
             assert next(iter(possibilities)).value == cur_addr
         else:
-            cur_path_constraint = set() # path_constraint for the concrete path
             for possibility in possibilities:
                 path_constraint = set() # Set of ExprAff for the possible path
 
@@ -622,6 +641,5 @@ class DSEPathConstraint(DSEEngine):
                         self.handle_solution(model, possibility.value)
                     self.cur_solver.pop()
 
-            # Update current solver
-            for cons in cur_path_constraint:
-                self.cur_solver.add(self.z3_trans.from_expr(cons))
+        self.handle_correct_destination(cur_addr, cur_path_constraint)
+
diff --git a/miasm2/arch/ppc/arch.py b/miasm2/arch/ppc/arch.py
index d47c2aad..87147f1c 100644
--- a/miasm2/arch/ppc/arch.py
+++ b/miasm2/arch/ppc/arch.py
@@ -115,7 +115,7 @@ class instruction_ppc(instruction):
             name = name[:-2] + 'A'
 
         if name[-2:] != 'LR' and name[-3:] != 'CTR':
-            if self.is_conditional_jump(name):
+            if len(self.args) == 2:
                 address_index = 1
             else:
                 address_index = 0
@@ -144,7 +144,7 @@ class instruction_ppc(instruction):
             return [ LR ]
         elif 'CTR' in self.name:
             return [ CTR ]
-        elif self.is_conditional_jump(self.name):
+        elif len(self.args) == 2:
             address_index = 1
         else:
             address_index = 0
@@ -462,9 +462,7 @@ def ppc_bo_bi_to_mnemo(bo, bi, prefer_taken=True, default_taken=True):
     return mnem
 
 def ppc_all_bo_bi():
-    yield 20, 0
-
-    for bo in [0, 2, 4, 8, 10, 12, 16, 18]:
+    for bo in [0, 2, 4, 8, 10, 12, 16, 18, 20]:
         for bi in xrange(4):
             yield bo, bi
 
diff --git a/miasm2/arch/ppc/sem.py b/miasm2/arch/ppc/sem.py
index 4434efa7..4923e3a8 100644
--- a/miasm2/arch/ppc/sem.py
+++ b/miasm2/arch/ppc/sem.py
@@ -428,7 +428,7 @@ def mn_do_nand(ir, instr, ra, rs, rb):
 
 def mn_do_neg(ir, instr, rd, ra):
     rvalue = -ra
-    ret = [ ExprAff(ra, rvalue) ]
+    ret = [ ExprAff(rd, rvalue) ]
     has_o = False
 
     over_expr = None
@@ -684,16 +684,17 @@ def mn_do_xor(ir, instr, ra, rs, rb):
 
     return ret, []
 
-@sbuild.parse
-def mn_b(arg1):
-    PC = arg1
-    ir.IRDst = arg1
-
-@sbuild.parse
-def mn_bl(arg1):
-    LR = ExprId(ir.get_next_instr(instr), 32)
-    PC = arg1
-    ir.IRDst = arg1
+def mn_b(ir, instr, arg1, arg2 = None):
+    if arg2 is not None:
+        arg1 = arg2
+    return [ ExprAff(PC, arg1), ExprAff(ir.IRDst, arg1) ], []
+
+def mn_bl(ir, instr, arg1, arg2 = None):
+    if arg2 is not None:
+        arg1 = arg2
+    return [ ExprAff(LR, ExprId(ir.get_next_instr(instr), 32)),
+             ExprAff(PC, arg1),
+             ExprAff(ir.IRDst, arg1) ], []
 
 def mn_get_condition(instr):
     bit = instr.additional_info.bi & 0b11