about summary refs log tree commit diff stats
path: root/miasm2/ir
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/ir')
-rw-r--r--miasm2/ir/analysis.py3
-rw-r--r--miasm2/ir/ir.py53
-rw-r--r--miasm2/ir/ir2C.py202
-rw-r--r--miasm2/ir/symbexec.py22
4 files changed, 165 insertions, 115 deletions
diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py
index c20c7f7a..eaa5f6c8 100644
--- a/miasm2/ir/analysis.py
+++ b/miasm2/ir/analysis.py
@@ -94,7 +94,6 @@ class ira:
                 for l in irs:
                     ir_txt.append(str(l))
                 ir_txt.append("")
-            ir_txt.append("DstBloc: %s" % str(b.dst))
             ir_txt.append("")
             all_lbls[id(lbl)] = "\l\\\n".join(ir_txt)
         for l, v in all_lbls.items():
@@ -212,7 +211,7 @@ class ira:
                 x = ExprId(r.name, r.size)
                 x.is_term = True
                 symbols_init[r] = x
-            sb = symbexec(self.arch, dict(symbols_init))
+            sb = symbexec(self, dict(symbols_init))
             sb.emulbloc(irb)
             eqs = []
             for n_w in sb.symbols:
diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py
index a5d079ca..9db6d696 100644
--- a/miasm2/ir/ir.py
+++ b/miasm2/ir/ir.py
@@ -30,17 +30,29 @@ from miasm2.core.asmbloc import asm_symbol_pool
 
 class irbloc:
 
-    def __init__(self, label, dst=None, irs=None, lines=None):
+    def __init__(self, label, irs, lines = []):
         assert(isinstance(label, asmbloc.asm_label))
         self.label = label
-        self.dst = dst
-        self.lines = []
-        self.irs = []
-        if irs is not None:
-            self.irs = irs
-        if lines is not None:
-            self.lines = lines
+        self.irs = irs
+        self.lines = lines
         self.except_automod = True
+        self._dst = None
+
+
+    def get_dst(self):
+        if self._dst is not None:
+            return self._dst
+        dst = None
+        for ir in self.irs:
+            for i in ir:
+                if isinstance(i.dst, m2_expr.ExprId) and i.dst.name == "IRDst":
+                    if dst is not None:
+                        raise ValueError('Multiple destinations!')
+                    dst = i.src
+        self._dst = dst
+        return dst
+
+    dst = property(get_dst)
 
     def get_rw(self):
         self.r = []
@@ -82,7 +94,6 @@ class irbloc:
             for e in expr:
                 o.append('\t%s' % e)
             o.append("")
-        o.append('\tDst: %s' % self.dst)
 
         return "\n".join(o)
 
@@ -100,8 +111,8 @@ class ir(object):
         self.attrib = attrib
 
     def instr2ir(self, l):
-        dst, ir_bloc_cur, ir_blocs_extra = self.get_ir(l)
-        return dst, ir_bloc_cur, ir_blocs_extra
+        ir_bloc_cur, ir_blocs_extra = self.get_ir(l)
+        return ir_bloc_cur, ir_blocs_extra
 
     def get_bloc(self, ad):
         if isinstance(ad, m2_expr.ExprId) and isinstance(ad.name,
@@ -194,28 +205,19 @@ class ir(object):
         ir_blocs_all = []
         for l in bloc.lines:
             if c is None:
-                # print 'new c'
                 label = self.get_label(l)
-                c = irbloc(label)
+                c = irbloc(label, [], [])
                 ir_blocs_all.append(c)
-                bloc_dst = None
-            # print 'Translate', l
-            dst, ir_bloc_cur, ir_blocs_extra = self.instr2ir(l)
-            # print ir_bloc_cur
-            # for xxx in ir_bloc_cur:
-            #    print "\t", xxx
-            assert((dst is None) or (bloc_dst is None))
-            bloc_dst = dst
-            if bloc_dst is not None:
-                c.dst = bloc_dst
+            ir_bloc_cur, ir_blocs_extra = self.instr2ir(l)
 
             if gen_pc_updt is not False:
                 self.gen_pc_update(c, l)
 
             c.irs.append(ir_bloc_cur)
             c.lines.append(l)
+
+
             if ir_blocs_extra:
-                # print 'split'
                 for b in ir_blocs_extra:
                     b.lines = [l] * len(b.irs)
                 ir_blocs_all += ir_blocs_extra
@@ -246,7 +248,8 @@ class ir(object):
                 continue
             dst = m2_expr.ExprId(self.get_next_label(bloc.lines[-1]),
                                  self.pc.size)
-            b.dst = dst
+            b.irs.append([m2_expr.ExprAff(self.IRDst, dst)])
+            b.lines.append(b.lines[-1])
 
     def gen_edges(self, bloc, ir_blocs):
         pass
diff --git a/miasm2/ir/ir2C.py b/miasm2/ir/ir2C.py
index 76620dc8..136f3e85 100644
--- a/miasm2/ir/ir2C.py
+++ b/miasm2/ir/ir2C.py
@@ -257,10 +257,12 @@ if (vmcpu->exception_flags && vmcpu->exception_flags > EXCEPT_NUM_UPDT_EIP) {
 code_exception_post_instr = r"""
 // except post instr
 if (vmcpu->exception_flags) {
-    if (vmcpu->exception_flags > EXCEPT_NUM_UPDT_EIP)
+    if (vmcpu->exception_flags > EXCEPT_NUM_UPDT_EIP) {
       %s;
-    else
+    }
+    else {
       %s;
+    }
     RETURN_PC;
 }
 """
@@ -275,14 +277,21 @@ if ((vmcpu->exception_flags & ~EXCEPT_CODE_AUTOMOD) && vmcpu->exception_flags >
 
 code_exception_post_instr_noautomod = r"""
 if (vmcpu->exception_flags & ~EXCEPT_CODE_AUTOMOD) {
-    if (vmcpu->exception_flags > EXCEPT_NUM_UPDT_EIP)
+    if (vmcpu->exception_flags > EXCEPT_NUM_UPDT_EIP) {
       %s;
-    else
+    }
+    else {
       %s;
+    }
     RETURN_PC;
 }
 """
 
+goto_local_code = r"""
+if (BlockDst.is_local) {
+    goto *local_labels[BlockDst.address];
+}
+"""
 
 my_size_mask = {1: 1, 2: 3, 3: 7, 7: 0x7f,
                 8: 0xFF,
@@ -293,15 +302,59 @@ my_size_mask = {1: 1, 2: 3, 3: 7, 7: 0x7f,
 exception_flags = ExprId('exception_flags', 32)
 
 
-def set_pc(my_ir, src):
-    dst = my_ir.jit_pc
+def set_pc(ir_arch, src):
+    dst = ir_arch.jit_pc
     if not isinstance(src, Expr):
         src = ExprInt_from(dst, src)
     e = ExprAff(dst, src.zeroExtend(dst.size))
     return e
 
 
-def Expr2C(my_ir, l, exprs, gen_exception_code=False):
+def gen_resolve_int(ir_arch, e):
+    return 'Resolve_dst(%X, 0)'%(e)
+
+def gen_resolve_id_lbl(ir_arch, e):
+    if e.name.name.startswith("lbl_gen_"):
+        # TODO XXX CLEAN
+        return 'Resolve_dst(0x%X, 1)'%(e.name.index)
+    else:
+        return 'Resolve_dst(0x%X, 0)'%(e.name.offset)
+
+def gen_resolve_id(ir_arch, e):
+    return 'Resolve_dst(%s, 0)'%(patch_c_id(ir_arch.arch, e).toC())
+
+def gen_resolve_mem(ir_arch, e):
+    return 'Resolve_dst(%s, 0)'%(patch_c_id(ir_arch.arch, e).toC())
+
+def gen_resolve_other(ir_arch, e):
+    return 'Resolve_dst(%s, 0)'%(patch_c_id(ir_arch.arch, e).toC())
+
+def gen_resolve_dst_simple(ir_arch, e):
+    if isinstance(e, ExprInt):
+        return gen_resolve_int(ir_arch, e)
+    elif isinstance(e, ExprId) and isinstance(e.name, asmbloc.asm_label):
+        return gen_resolve_id_lbl(ir_arch, e)
+    elif isinstance(e, ExprId):
+        return gen_resolve_id(ir_arch, e)
+    elif isinstance(e, ExprMem):
+        return gen_resolve_mem(ir_arch, e)
+    else:
+        return gen_resolve_other(ir_arch, e)
+
+
+def gen_irdst(ir_arch, e):
+    out = []
+    if isinstance(e, ExprCond):
+        dst_cond_c = patch_c_id(ir_arch.arch, e.cond).toC()
+        out.append("if (%s)"%dst_cond_c)
+        out.append('    BlockDst = %s;'%(gen_resolve_dst_simple(ir_arch, e.src1)))
+        out.append("else")
+        out.append('    BlockDst = %s;'%(gen_resolve_dst_simple(ir_arch, e.src2)))
+    else:
+        out.append('BlockDst = %s;'%(gen_resolve_dst_simple(ir_arch, e)))
+    return out
+
+def Expr2C(ir_arch, l, exprs, gen_exception_code=False):
     id_to_update = []
     out = ["// %s" % (l)]
     out_pc = []
@@ -312,8 +365,8 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
     prefect_index = {8: 0, 16: 0, 32: 0, 64: 0}
     new_expr = []
 
-    e = set_pc(my_ir, l.offset & mask_int)
-    #out.append("%s;" % patch_c_id(my_ir.arch, e).toC())
+    e = set_pc(ir_arch, l.offset & mask_int)
+    #out.append("%s;" % patch_c_id(ir_arch.arch, e).toC())
 
     pc_is_dst = False
     fetch_mem = False
@@ -360,22 +413,31 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
     mem_k = src_mem.keys()
     mem_k.sort()
     for k in mem_k:
-        str_src = patch_c_id(my_ir.arch, k).toC()
-        str_dst = patch_c_id(my_ir.arch, src_mem[k]).toC()
+        str_src = patch_c_id(ir_arch.arch, k).toC()
+        str_dst = patch_c_id(ir_arch.arch, src_mem[k]).toC()
         out.append('%s = %s;' % (str_dst, str_src))
     src_w_len = {}
     for k, v in src_mem.items():
         src_w_len[k] = v
     for e in new_expr:
+
         src, dst = e.src, e.dst
         # reload src using prefetch
         src = src.replace_expr(src_w_len)
-        str_src = patch_c_id(my_ir.arch, src).toC()
-        str_dst = patch_c_id(my_ir.arch, dst).toC()
+        if dst is ir_arch.IRDst:
+            out += gen_irdst(ir_arch, src)
+            continue
+
+
+        str_src = patch_c_id(ir_arch.arch, src).toC()
+        str_dst = patch_c_id(ir_arch.arch, dst).toC()
+
+
+
         if isinstance(dst, ExprId):
             id_to_update.append(dst)
-            str_dst = patch_c_new_id(my_ir.arch, dst)
-            if dst in my_ir.arch.regs.regs_flt_expr:
+            str_dst = patch_c_new_id(ir_arch.arch, dst)
+            if dst in ir_arch.arch.regs.regs_flt_expr:
                 # dont mask float affectation
                 out.append('%s = (%s);' % (str_dst, str_src))
             else:
@@ -386,7 +448,7 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
             str_dst = str_dst.replace('MEM_LOOKUP', 'MEM_WRITE')
             out_mem.append('%s, %s);' % (str_dst[:-1], str_src))
 
-        if e.dst == my_ir.arch.pc[my_ir.attrib]:
+        if e.dst == ir_arch.arch.pc[ir_arch.attrib]:
             pc_is_dst = True
             out_pc += ["RETURN_PC;"]
 
@@ -397,17 +459,21 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
 
     if gen_exception_code:
         if fetch_mem:
-            e = set_pc(my_ir, l.offset & mask_int)
-            s1 = "%s" % patch_c_id(my_ir.arch, e).toC()
+            e = set_pc(ir_arch, l.offset & mask_int)
+            s1 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+            s1 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%(l.offset & mask_int)
             out.append(code_exception_fetch_mem_at_instr_noautomod % s1)
         if set_exception_flags:
-            e = set_pc(my_ir, l.offset & mask_int)
-            s1 = "%s" % patch_c_id(my_ir.arch, e).toC()
+            e = set_pc(ir_arch, l.offset & mask_int)
+            s1 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+            s1 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%(l.offset & mask_int)
             out.append(code_exception_at_instr_noautomod % s1)
 
     for i in id_to_update:
+        if i is ir_arch.IRDst:
+            continue
         out.append('%s = %s;' %
-                   (patch_c_id(my_ir.arch, i), patch_c_new_id(my_ir.arch, i)))
+                   (patch_c_id(ir_arch.arch, i), patch_c_new_id(ir_arch.arch, i)))
 
     post_instr = []
     # test stop exec ####
@@ -417,10 +483,12 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
                 post_instr.append("if (vm_mngr->exception_flags) { " +
                     "/*pc = 0x%X; */RETURN_PC; }" % (l.offset))
             else:
-                e = set_pc(my_ir, l.offset & mask_int)
-                s1 = "%s" % patch_c_id(my_ir.arch, e).toC()
-                e = set_pc(my_ir, (l.offset + l.l) & mask_int)
-                s2 = "%s" % patch_c_id(my_ir.arch, e).toC()
+                e = set_pc(ir_arch, l.offset & mask_int)
+                s1 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+                s1 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%(l.offset & mask_int)
+                e = set_pc(ir_arch, (l.offset + l.l) & mask_int)
+                s2 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+                s2 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%((l.offset + l.l) & mask_int)
                 post_instr.append(
                     code_exception_post_instr_noautomod % (s1, s2))
 
@@ -430,8 +498,9 @@ def Expr2C(my_ir, l, exprs, gen_exception_code=False):
             else:
                 offset = l.offset + l.l
 
-            e = set_pc(my_ir, offset & mask_int)
-            s1 = "%s" % patch_c_id(my_ir.arch, e).toC()
+            e = set_pc(ir_arch, offset & mask_int)
+            s1 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+            s1 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%(offset & mask_int)
             post_instr.append(
                 code_exception_fetch_mem_post_instr_noautomod % (s1))
 
@@ -459,17 +528,19 @@ def expr2pyobj(arch, e):
     return src_c
 
 
-def ir2C(my_ir, irbloc, lbl_done,
+def ir2C(ir_arch, irbloc, lbl_done,
     gen_exception_code=False, log_mn=False, log_regs=False):
     out = []
     # print "TRANS"
     # print irbloc
     out.append(["%s:" % irbloc.label.name])
+    #out.append(['printf("%s:\n");' % irbloc.label.name])
     assert(len(irbloc.irs) == len(irbloc.lines))
     for l, exprs in zip(irbloc.lines, irbloc.irs):
         if l.offset not in lbl_done:
-            e = set_pc(my_ir, l.offset & mask_int)
-            s1 = "%s" % patch_c_id(my_ir.arch, e).toC()
+            e = set_pc(ir_arch, l.offset & mask_int)
+            s1 = "%s" % patch_c_id(ir_arch.arch, e).toC()
+            s1 += ';\n    BlockDst = Resolve_dst(0x%X, 0);\n'%(l.offset & mask_int)
             out.append([pre_instr_test_exception % (s1)])
             lbl_done.add(l.offset)
 
@@ -481,14 +552,34 @@ def ir2C(my_ir, irbloc, lbl_done,
         # print l
         # gen pc update
         post_instr = ""
-        c_code, post_instr, _ = Expr2C(my_ir, l, exprs, gen_exception_code)
+        c_code, post_instr, _ = Expr2C(ir_arch, l, exprs, gen_exception_code)
         out.append(c_code + post_instr)
+    out.append([goto_local_code ] )
     return out
 
 
-def irblocs2C(my_ir, resolvers, label, irblocs,
+def irblocs2C(ir_arch, resolvers, label, irblocs,
     gen_exception_code=False, log_mn=False, log_regs=False):
     out = []
+    out.append("block_id BlockDst = {0, 0};")
+    lbls = [b.label for b in irblocs]
+    lbls_local = []
+    for l in lbls:
+        if l.name.startswith('lbl_gen_'):
+            l.index = int(l.name[8:], 16)
+            lbls_local.append(l)
+    lbl_index_min, lbl_index_max = 0, 0
+    lbls_index = [l.index for l in lbls if hasattr(l, 'index')]
+    lbls_local.sort(key=lambda x:x.index)
+
+    if lbls_index:
+        lbl_index_min = min(lbls_index)
+        lbl_index_max = max(lbls_index)
+        for l in lbls_local:
+            l.index -= lbl_index_min
+
+    out.append("void* local_labels[] = {%s};"%(', '.join(["&&%s"%l.name for l in lbls_local])))
+
     out.append("goto %s;" % label.name)
     bloc_labels = [x.label for x in irblocs]
     assert(label in bloc_labels)
@@ -498,57 +589,16 @@ def irblocs2C(my_ir, resolvers, label, irblocs,
     for irbloc in irblocs:
         # XXXX TEST
         if irbloc.label.offset is None:
-            b_out = ir2C(my_ir, irbloc, lbl_done, gen_exception_code)
+            b_out = ir2C(ir_arch, irbloc, lbl_done, gen_exception_code)
         else:
             b_out = ir2C(
-                my_ir, irbloc, lbl_done, gen_exception_code, log_mn, log_regs)
+                ir_arch, irbloc, lbl_done, gen_exception_code, log_mn, log_regs)
         for exprs in b_out:
             for l in exprs:
                 out.append(l)
         dst = irbloc.dst
         out.append("")
-        if asmbloc.expr_is_label(dst):
-            if dst.name in bloc_labels:
-                out.append("goto %s;" % dst.name.name)
-            else:
-                resolver = resolvers.get_resolver(dst.name.offset)
-
-                e = set_pc(my_ir, dst.name.offset & mask_int)
-                #out.append("%s;" % patch_c_id(my_ir.arch, e).toC())
-                out.append(resolver.ret())
-        elif isinstance(dst, ExprSlice) and isinstance(dst.arg, ExprId):
-            e = set_pc(my_ir, dst)
-            #out.append("%s;" % patch_c_id(my_ir.arch, e).toC())
-
-            e = patch_c_id(my_ir.arch, dst).toC()
-            out.append("return PyLong_FromUnsignedLongLong(%s);" % e)
-
-        elif isinstance(dst, ExprId):
-            e = set_pc(my_ir, dst)
-            #out.append("%s;" % patch_c_id(my_ir.arch, e).toC())
-
-            e = patch_c_id(my_ir.arch, dst).toC()
-            out.append("return PyLong_FromUnsignedLongLong(%s);" % e)
-        elif isinstance(dst, ExprCond):
-            dst_cond_c = patch_c_id(my_ir.arch, dst.cond).toC()
-            out.append("if (%s)" % dst_cond_c)
-
-            if dst.src1.name in bloc_labels:
-                out.append("    goto %s;" % dst.src1.name.name)
-            else:
-                resolver = resolvers.get_resolver(dst.src1.name.offset)
-                out.append(resolver.ret())
-
-            out.append("else")
+        out.append("return BlockDst;")
 
-            if dst.src2.name in bloc_labels:
-                out.append("    goto %s;" % dst.src2.name.name)
-            else:
-                resolver = resolvers.get_resolver(dst.src2.name.offset)
-                out.append(resolver.ret())
-
-        else:
-            raise NotImplementedError('unknown type for dst: %s' % type(dst))
-    #print '\n'.join(out)
     return out
 
diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py
index 08608142..3954a543 100644
--- a/miasm2/ir/symbexec.py
+++ b/miasm2/ir/symbexec.py
@@ -81,7 +81,7 @@ class symbols():
 
 class symbexec:
 
-    def __init__(self, arch, known_symbols,
+    def __init__(self, ir_arch, known_symbols,
                  func_read=None,
                  func_write=None,
                  sb_expr_simp=expr_simp):
@@ -90,7 +90,7 @@ class symbexec:
             self.symbols[k] = v
         self.func_read = func_read
         self.func_write = func_write
-        self.arch = arch
+        self.ir_arch = ir_arch
         self.expr_simp = sb_expr_simp
 
     def find_mem_by_addr(self, e):
@@ -220,7 +220,7 @@ class symbexec:
 
     def modified_regs(self, init_state=None):
         if init_state is None:
-            init_state = self.arch.regs.regs_init
+            init_state = self.ir_arch.arch.regs.regs_init
         ids = self.symbols.symbols_id.keys()
         ids.sort()
         for i in ids:
@@ -246,9 +246,9 @@ class symbexec:
         ids = self.symbols.symbols_id.keys()
         ids.sort()
         for i in ids:
-            if i in self.arch.regs.regs_init and \
+            if i in self.ir_arch.arch.regs.regs_init and \
                     i in self.symbols.symbols_id and \
-                    self.symbols.symbols_id[i] == self.arch.regs.regs_init[i]:
+                    self.symbols.symbols_id[i] == self.ir_arch.arch.regs.regs_init[i]:
                 continue
             print i, self.symbols.symbols_id[i]
 
@@ -401,24 +401,22 @@ class symbexec:
             if step:
                 print '_' * 80
                 self.dump_id()
-        if bloc_ir.dst is None:
-            return None
-        return self.eval_expr(bloc_ir.dst)
+        return self.eval_expr(self.ir_arch.IRDst)
 
-    def emul_ir_bloc(self, myir, ad):
+    def emul_ir_bloc(self, myir, ad, step = False):
         b = myir.get_bloc(ad)
         if b is not None:
-            ad = self.emulbloc(b)
+            ad = self.emulbloc(b, step = step)
         return ad
 
-    def emul_ir_blocs(self, myir, ad, lbl_stop=None):
+    def emul_ir_blocs(self, myir, ad, lbl_stop=None, step = False):
         while True:
             b = myir.get_bloc(ad)
             if b is None:
                 break
             if b.label == lbl_stop:
                 break
-            ad = self.emulbloc(b)
+            ad = self.emulbloc(b, step = step)
         return ad
 
     def del_mem_above_stack(self, sp):