about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/ida/ctype_propagation.py13
-rw-r--r--miasm2/arch/arm/arch.py4
-rw-r--r--miasm2/arch/arm/ira.py61
-rw-r--r--miasm2/arch/mips32/ira.py5
-rw-r--r--miasm2/arch/ppc/ira.py37
-rw-r--r--miasm2/arch/x86/arch.py2
-rw-r--r--miasm2/arch/x86/ira.py31
-rw-r--r--miasm2/core/cpu.py2
-rw-r--r--miasm2/ir/analysis.py27
-rw-r--r--test/arch/x86/unit/test_asm_x86_64.py30
-rwxr-xr-xtest/test_all.py1
11 files changed, 158 insertions, 55 deletions
diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py
index e8b52e3e..3c8a745a 100644
--- a/example/ida/ctype_propagation.py
+++ b/example/ida/ctype_propagation.py
@@ -230,11 +230,14 @@ def get_ira_call_fixer(ira):
             stk_after = idc.GetSpd(instr.offset + instr.l)
             stk_diff = stk_after - stk_before
             print hex(stk_diff)
-            return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad)),
-                                 ExprAff(self.sp, self.sp + ExprInt(stk_diff, self.sp.size))
-                                 ],
-                                instr
-                                )]
+            call_assignblk = AssignBlock(
+                [
+                    ExprAff(self.ret_reg, ExprOp('call_func_ret', ad)),
+                    ExprAff(self.sp, self.sp + ExprInt(stk_diff, self.sp.size))
+                ],
+                instr
+            )
+            return [call_assignblk], []
 
     return iraCallStackFixer
 
diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py
index 82664476..e25e4911 100644
--- a/miasm2/arch/arm/arch.py
+++ b/miasm2/arch/arm/arch.py
@@ -420,6 +420,8 @@ class instruction_arm(instruction):
 
 
     def dstflow(self):
+        if self.is_subcall():
+            return True
         return self.name in conditional_branch + unconditional_branch
 
     def dstflow2label(self, loc_db):
@@ -434,6 +436,8 @@ class instruction_arm(instruction):
         self.args[0] = ExprLoc(loc_key, expr.size)
 
     def breakflow(self):
+        if self.is_subcall():
+            return True
         if self.name in conditional_branch + unconditional_branch:
             return True
         if self.name.startswith("LDM") and PC in self.args[1].args:
diff --git a/miasm2/arch/arm/ira.py b/miasm2/arch/arm/ira.py
index 7b26a6e4..fd8096d7 100644
--- a/miasm2/arch/arm/ira.py
+++ b/miasm2/arch/arm/ira.py
@@ -1,8 +1,9 @@
 #-*- coding:utf-8 -*-
 
 from miasm2.ir.analysis import ira
-from miasm2.arch.arm.sem import ir_arml, ir_armtl, ir_armb, ir_armtb
-from miasm2.expression.expression import ExprAff, ExprOp
+from miasm2.ir.ir import IRBlock
+from miasm2.arch.arm.sem import ir_arml, ir_armtl, ir_armb, ir_armtb, tab_cond
+from miasm2.expression.expression import ExprAff, ExprOp, ExprLoc, ExprCond
 from miasm2.ir.ir import AssignBlock
 
 class ir_a_arml_base(ir_arml, ira):
@@ -23,17 +24,51 @@ class ir_a_arml(ir_a_arml_base):
         self.ret_reg = self.arch.regs.R0
 
     def call_effects(self, ad, instr):
-        return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad,
-                                                          self.arch.regs.R0,
-                                                          self.arch.regs.R1,
-                                                          self.arch.regs.R2,
-                                                          self.arch.regs.R3,
-                                                          )),
-                             ExprAff(self.sp, ExprOp('call_func_stack',
-                                                     ad, self.sp)),
-                            ],
-                             instr
-                           )]
+        call_assignblk = AssignBlock(
+            [
+                ExprAff(
+                    self.ret_reg,
+                    ExprOp(
+                        'call_func_ret',
+                        ad,
+                        self.arch.regs.R0,
+                        self.arch.regs.R1,
+                        self.arch.regs.R2,
+                        self.arch.regs.R3,
+                    )
+                ),
+                ExprAff(
+                    self.sp,
+                    ExprOp('call_func_stack', ad, self.sp)
+                ),
+            ],
+            instr
+        )
+
+
+        cond = instr.additional_info.cond
+        if cond == 14: # COND_ALWAYS:
+            return [call_assignblk], []
+
+        # Call is a conditional instruction
+        cond = tab_cond[cond]
+
+        loc_next = self.get_next_loc_key(instr)
+        loc_next_expr = ExprLoc(loc_next, 32)
+        loc_do = self.loc_db.add_location()
+        loc_do_expr = ExprLoc(loc_do, 32)
+        dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr)
+
+        call_assignblks = [
+            call_assignblk,
+            AssignBlock([ExprAff(self.IRDst, loc_next_expr)], instr),
+        ]
+        e_do = IRBlock(loc_do, call_assignblks)
+        assignblks_out = [
+            AssignBlock([ExprAff(self.IRDst, dst_cond)], instr)
+        ]
+        return assignblks_out, [e_do]
+
 
     def get_out_regs(self, _):
         return set([self.ret_reg, self.sp])
diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py
index 3caa8b12..def75750 100644
--- a/miasm2/arch/mips32/ira.py
+++ b/miasm2/arch/mips32/ira.py
@@ -37,11 +37,12 @@ class ir_a_mips32l(ir_mips32l, ira):
             # CALL
             lbl = block.get_next()
             new_lbl = self.gen_label()
-            irs = self.call_effects(pc_val, instr)
+            call_assignblks, extra_irblocks = self.call_effects(pc_val, instr)
+            ir_blocks += extra_irblocks
             irs.append(AssignBlock([ExprAff(self.IRDst,
                                             ExprId(lbl, size=self.pc.size))],
                                    instr))
-            new_irblocks.append(IRBlock(new_lbl, irs))
+            new_irblocks.append(IRBlock(new_lbl, call_assignblks))
             new_irblocks.append(irb.set_dst(ExprId(new_lbl, size=self.pc.size)))
         return new_irblocks
 
diff --git a/miasm2/arch/ppc/ira.py b/miasm2/arch/ppc/ira.py
index a30f972d..79476e90 100644
--- a/miasm2/arch/ppc/ira.py
+++ b/miasm2/arch/ppc/ira.py
@@ -23,17 +23,24 @@ class ir_a_ppc32b(ir_ppc32b, ira):
             self.set_dead_regs(irblock)
 
     def call_effects(self, ad, instr):
-        return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad,
-                                                          self.sp,
-                                                          self.arch.regs.R3,
-                                                          self.arch.regs.R4,
-                                                          self.arch.regs.R5,
-                                                          )),
-                             ExprAff(self.sp, ExprOp('call_func_stack',
-                                                     ad, self.sp)),
-                            ],
-                             instr
-                           )]
+        call_assignblks = AssignBlock(
+            [
+                ExprAff(
+                    self.ret_reg,
+                    ExprOp(
+                        'call_func_ret',
+                        ad,
+                        self.sp,
+                        self.arch.regs.R3,
+                        self.arch.regs.R4,
+                        self.arch.regs.R5,
+                    )
+                ),
+                ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)),
+            ],
+            instr
+        )
+        return [call_assignblks], []
 
     def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
         """
@@ -46,8 +53,12 @@ class ir_a_ppc32b(ir_ppc32b, ira):
         @gen_pc_updt: insert PC update effects between instructions
         """
         if instr.is_subcall():
-            call_effects = self.call_effects(instr.getdstflow(None)[0], instr)
-            assignments+= call_effects
+            call_assignblks, extra_irblocks = self.call_effects(
+                instr.getdstflow(None)[0],
+                instr
+            )
+            assignments += call_assignblks
+            ir_blocks_all += extra_irblocks
             return True
 
         if gen_pc_updt is not False:
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index bf872667..3a0fb78e 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -256,7 +256,7 @@ cl_or_imm |= base_expr
 class x86_arg(m_arg):
     def asm_ast_to_expr(self, value, loc_db, size_hint=None, fixed_size=None):
         if size_hint is None:
-            size_hint = self.parent.v_opmode()
+            size_hint = self.parent.mode
         if fixed_size is None:
             fixed_size = set()
         if isinstance(value, AstId):
diff --git a/miasm2/arch/x86/ira.py b/miasm2/arch/x86/ira.py
index be10213e..a95e6c69 100644
--- a/miasm2/arch/x86/ira.py
+++ b/miasm2/arch/x86/ira.py
@@ -44,18 +44,25 @@ class ir_a_x86_64(ir_x86_64, ir_a_x86_16):
         self.ret_reg = self.arch.regs.RAX
 
     def call_effects(self, ad, instr):
-        return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad,
-                                                          self.sp,
-                                                          self.arch.regs.RCX,
-                                                          self.arch.regs.RDX,
-                                                          self.arch.regs.R8,
-                                                          self.arch.regs.R9,
-                                                          )),
-                             ExprAff(self.sp, ExprOp('call_func_stack',
-                                                     ad, self.sp)),
-                            ],
-                             instr
-                           )]
+        call_assignblk = AssignBlock(
+            [
+                ExprAff(
+                    self.ret_reg,
+                    ExprOp(
+                        'call_func_ret',
+                        ad,
+                        self.sp,
+                        self.arch.regs.RCX,
+                        self.arch.regs.RDX,
+                        self.arch.regs.R8,
+                        self.arch.regs.R9,
+                    )
+                ),
+                ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)),
+            ],
+            instr
+        )
+        return [call_assignblk], []
 
     def sizeof_char(self):
         return 8
diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py
index 1326d08b..686e12ba 100644
--- a/miasm2/core/cpu.py
+++ b/miasm2/core/cpu.py
@@ -1036,7 +1036,7 @@ class instruction(object):
                 offset = symbols.get_location_offset(loc_key)
                 if offset is None:
                     raise ValueError(
-                        'The offset of loc_key "%s" cannot be determined' % name
+                        'The offset of loc_key "%s" cannot be determined' % names
                     )
                 else:
                     # Fix symbol with its offset
diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py
index 962b9889..d49f6b4e 100644
--- a/miasm2/ir/analysis.py
+++ b/miasm2/ir/analysis.py
@@ -4,7 +4,7 @@ import warnings
 import logging
 
 from miasm2.ir.ir import IntermediateRepresentation, AssignBlock
-from miasm2.expression.expression import ExprOp
+from miasm2.expression.expression import ExprOp, ExprAff
 from miasm2.analysis.data_flow import dead_simp as new_dead_simp_imp
 
 
@@ -35,15 +35,22 @@ class ira(IntermediateRepresentation):
         * insert dependencies to arguments (stack base, registers, ...)
         * add some side effects (stack clean, return value, ...)
 
+        Return a couple:
+        * list of assignments to add to the current irblock
+        * list of additional irblocks
+
         @addr: (Expr) address of the called function
         @instr: native instruction which is responsible of the call
         """
 
-        assignblk = AssignBlock({
-            self.ret_reg: ExprOp('call_func_ret', addr, self.sp),
-            self.sp: ExprOp('call_func_stack', addr, self.sp)},
-            instr)
-        return [assignblk]
+        call_assignblk = AssignBlock(
+            [
+                ExprAff(self.ret_reg, ExprOp('call_func_ret', addr, self.sp)),
+                ExprAff(self.sp, ExprOp('call_func_stack', addr, self.sp))
+            ],
+            instr
+        )
+        return [call_assignblk], []
 
     def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
         """
@@ -62,8 +69,12 @@ class ira(IntermediateRepresentation):
         @gen_pc_updt: insert PC update effects between instructions
         """
         if instr.is_subcall():
-            call_effects = self.call_effects(instr.args[0], instr)
-            assignments+= call_effects
+            call_assignblks, extra_irblocks = self.call_effects(
+                instr.args[0],
+                instr
+            )
+            assignments += call_assignblks
+            ir_blocks_all += extra_irblocks
             return True
 
         if gen_pc_updt is not False:
diff --git a/test/arch/x86/unit/test_asm_x86_64.py b/test/arch/x86/unit/test_asm_x86_64.py
new file mode 100644
index 00000000..4e600846
--- /dev/null
+++ b/test/arch/x86/unit/test_asm_x86_64.py
@@ -0,0 +1,30 @@
+from miasm2.core import asmblock
+from miasm2.arch.x86  import arch
+from miasm2.core import parse_asm
+from miasm2.core.interval import interval
+
+my_mn = arch.mn_x86
+
+
+asmcfg, loc_db = parse_asm.parse_txt(my_mn, 64, r'''
+main:
+  PUSH   RBP
+  MOV    RBP, RSP
+loop_dec:
+  CMP    RCX, RDX
+  JB    loop_dec
+end:
+  MOV    RSP, RBP
+  POP    RBP
+  RET
+
+''')
+
+loc_db.set_location_offset(loc_db.get_name_location("main"), 0x100001000)
+dst_interval = interval([(0x100001000, 0x100002000)])
+patches = asmblock.asm_resolve_final(
+    my_mn,
+    asmcfg,
+    loc_db,
+    dst_interval
+)
diff --git a/test/test_all.py b/test/test_all.py
index 81b6e6e5..3fb0a5b7 100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -81,6 +81,7 @@ for script in ["x86/sem.py",
                "x86/unit/mn_seh.py",
                "x86/unit/mn_cpuid.py",
                "x86/unit/mn_div.py",
+               "x86/unit/test_asm_x86_64.py",
                "arm/arch.py",
                "arm/sem.py",
                "aarch64/unit/mn_ubfm.py",