about summary refs log tree commit diff stats
path: root/miasm2
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2')
-rw-r--r--miasm2/arch/arm/arch.py7
-rw-r--r--miasm2/arch/sh4/arch.py3
-rw-r--r--miasm2/core/asmbloc.py42
-rw-r--r--miasm2/core/cpu.py11
-rw-r--r--miasm2/core/parse_asm.py67
-rw-r--r--miasm2/core/utils.py7
-rw-r--r--miasm2/jitter/jitload.py10
7 files changed, 104 insertions, 43 deletions
diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py
index dbcb62de..dd0cf665 100644
--- a/miasm2/arch/arm/arch.py
+++ b/miasm2/arch/arm/arch.py
@@ -319,18 +319,15 @@ class instruction_arm(instruction):
 
     def fixDstOffset(self):
         e = self.args[0]
-        print 'FIX', e, self.offset, self.l
         if self.offset is None:
             raise ValueError('symbol not resolved %s' % l)
         if not isinstance(e, ExprInt):
-            log.warning('zarb dst %r' % e)
+            log.debug('dyn dst %r' % e)
             return
         off = e.arg - (self.offset + 4 + self.l)
-        print hex(off)
         if int(off % 4):
             raise ValueError('strange offset! %r' % off)
         self.args[0] = ExprInt32(off)
-        print 'final', self.args[0]
 
     def get_args_expr(self):
         args = [a for a in self.args]
@@ -502,7 +499,7 @@ class mn_arm(cls_mn):
             raise ValueError('symbol not resolved %s' % l)
         if not isinstance(e, ExprInt):
             # raise ValueError('dst must be int or label')
-            log.warning('zarb dst %r' % e)
+            log.debug('dyn dst %r' % e)
             return
         # return ExprInt32(e.arg - (self.offset + self.l))
         off = e.arg - (self.offset + 4 + self.l)
diff --git a/miasm2/arch/sh4/arch.py b/miasm2/arch/sh4/arch.py
index c2029000..d07e631d 100644
--- a/miasm2/arch/sh4/arch.py
+++ b/miasm2/arch/sh4/arch.py
@@ -444,11 +444,10 @@ class instruction_sh4(instruction):
 
     def fixDstOffset(self):
         e = self.args[0]
-        print 'FIX', e, self.offset, self.l
         if self.offset is None:
             raise ValueError('symbol not resolved %s' % l)
         if not isinstance(e, ExprInt):
-            log.warning('zarb dst %r' % e)
+            log.debug('dyn dst %r' % e)
             return
         off = e.arg - (self.offset + 4 + self.l)
         print hex(off)
diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py
index 5770c82b..fc2edd30 100644
--- a/miasm2/core/asmbloc.py
+++ b/miasm2/core/asmbloc.py
@@ -3,10 +3,13 @@
 
 import logging
 import miasm2.expression.expression as m2_expr
+from miasm2.expression.simplifications import expr_simp
+
 from miasm2.expression.modint import moduint, modint
 from miasm2.core.graph import DiGraph
-from utils import Disasm_Exception
+from miasm2.core.utils import Disasm_Exception, pck
 from miasm2.core.graph import DiGraph
+
 import inspect
 
 log_asmbloc = logging.getLogger("asmbloc")
@@ -78,7 +81,6 @@ class asm_label:
 
 
 class asm_raw:
-
     def __init__(self, raw=""):
         self.raw = raw
 
@@ -327,7 +329,7 @@ class asm_symbol_pool:
     def set_offset(self, label, offset):
         # Note that there is a special case when the offset is a list
         # it happens when offsets are recomputed in resolve_symbol*
-        if not label in self.labels:
+        if not label.name in self.s:
             raise ValueError('label %s not in symbol pool' % label)
         if not isinstance(label.offset, list) and label.offset in self.s_offset:
             del(self.s_offset[label.offset])
@@ -634,6 +636,16 @@ def conservative_asm(mnemo, mode, instr, symbols, conservative):
                 return c, candidates
     return candidates[0], candidates
 
+def fix_expr_val(e, symbols):
+    def expr_calc(e):
+        if isinstance(e, m2_expr.ExprId):
+            s = symbols.s[e.name]
+            e = m2_expr.ExprInt_from(e, s.offset)
+        return e
+    e = e.visit(expr_calc)
+    e = expr_simp(e)
+    return e
+
 
 def guess_blocs_size(mnemo, mode, blocs, symbols):
     """
@@ -645,10 +657,18 @@ def guess_blocs_size(mnemo, mode, blocs, symbols):
         blen_max = 0
         for instr in b.lines:
             if isinstance(instr, asm_raw):
-                candidates = [instr.raw]
-                c = instr.raw
-                data = c
-                l = len(c)
+                # for special asm_raw, only extract len
+                if isinstance(instr.raw, list):
+                    data = None
+                    if len(instr.raw) == 0:
+                        l = 0
+                    else:
+                        l = instr.raw[0].size/8 * len(instr.raw)
+                elif isinstance(instr.raw, str):
+                    data = instr.raw
+                    l = len(data)
+                else:
+                    raise NotImplementedError('asm raw')
             else:
                 l = mnemo.max_instruction_len
                 data = None
@@ -961,6 +981,14 @@ def asmbloc_final(mnemo, mode, blocs, symbol_pool, symb_reloc_off=None, conserva
             my_symb_reloc_off[b.label] = []
             for instr in b.lines:
                 if isinstance(instr, asm_raw):
+                    if isinstance(instr.raw, list):
+                        # fix special asm_raw
+                        data = ""
+                        for x in instr.raw:
+                            e = fix_expr_val(x, symbols)
+                            data+= pck[e.size](e.arg)
+                        instr.data = data
+
                     offset_i += instr.l
                     continue
                 sav_a = instr.args[:]
diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py
index b1034327..2d52eac0 100644
--- a/miasm2/core/cpu.py
+++ b/miasm2/core/cpu.py
@@ -161,10 +161,18 @@ def ast_parse_op(t):
             return ExprOp(t[0], t[1])
     if len(t) == 3:
         args = [t[0], t[2]]
+        if t[1] == '-':
+            # a - b => a + (-b)
+            t[1] = '+'
+            t[2] = - t[2]
         return ExprOp(t[1], t[0], t[2])
     t = t[::-1]
     while len(t) >= 3:
         o1, op, o2 = t.pop(), t.pop(), t.pop()
+        if op == '-':
+            # a - b => a + (-b)
+            op = '+'
+            o2 = - o2
         e = ExprOp(op, o1, o2)
         t.append(e)
     if len(t) != 1:
@@ -1377,8 +1385,7 @@ class cls_mn(object):
         if len(out) == 0:
             raise ValueError('cannot fromstring %r' % s)
         if len(out) != 1:
-            log.warning('fromstring multiple args ret default')
-            # raise ValueError("cannot parse %r (%d cand)"%(s, len(out)))
+            log.debug('fromstring multiple args ret default')
         c = out[0]
         c_args = out_args[0]
 
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py
index c8967dab..f29a9839 100644
--- a/miasm2/core/parse_asm.py
+++ b/miasm2/core/parse_asm.py
@@ -5,14 +5,21 @@ import re
 import struct
 import miasm2.expression.expression as m2_expr
 from miasm2.core.asmbloc import *
-
-declarator = {'byte': 'B',
-              'word': 'H',
-              'dword': 'I',
-              'qword': 'Q',
-              'long': 'I', 'zero': 'I',
+from miasm2.core.utils import pck
+from miasm2.core.cpu import gen_base_expr, parse_ast
+declarator = {'byte': 8,
+              'word': 16,
+              'dword': 32,
+              'qword': 64,
+              'long': 32,
               }
 
+size2pck = {8: 'B',
+            16: 'H',
+            32: 'I',
+            64: 'Q',
+            }
+
 
 def guess_next_new_label(symbol_pool, gen_label_index=0):
     i = 0
@@ -70,6 +77,7 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None, gen_label_index=0):
                 # XXX HACK
                 line = line.replace(r'\n', '\n').replace(r'\r', '\r')
                 raw = line[line.find(r'"') + 1:line.rfind(r"'")]
+                raw = raw.decode('string_escape')
                 if directive == 'string':
                     raw += "\x00"
                 lines.append(asm_raw(raw))
@@ -78,29 +86,40 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None, gen_label_index=0):
                 # XXX HACK
                 line = line.replace(r'\n', '\n').replace(r'\r', '\r')
                 raw = line[line.find(r'"') + 1:line.rfind(r"'")] + "\x00"
+                raw = raw.decode('string_escape')
                 raw = "".join(map(lambda x: x + '\x00', raw))
                 lines.append(asm_raw(raw))
                 continue
             if directive in declarator:
-                data_raw = line[r.end():].split()
-                try:
-                    data_int = []
-                    for b in data_raw:
-                        if re.search(r'0x', b):
-                            data_int.append(int(b, 16))
-                        else:
-                            data_int.append(int(b) % (1 << 32))
-                    raw = reduce(lambda x, y: x + struct.pack(
-                        declarator[directive], y), data_int, "")
-                except ValueError:
-                    raw = line
-                lines.append(asm_raw(raw))
+                data_raw = line[r.end():].split(' ', 1)[1]
+                data_raw = data_raw.split(',')
+                size = declarator[directive]
+                data_int = []
+                has_symb = False
+
+                # parser
+                variable, operand, base_expr = gen_base_expr()
+                my_var_parser = parse_ast(lambda x:m2_expr.ExprId(x, size),
+                                          lambda x:m2_expr.ExprInt_fromsize(size, x))
+                base_expr.setParseAction(my_var_parser)
+
+                for b in data_raw:
+                    b = b.strip()
+                    x = base_expr.parseString(b)[0]
+                    data_int.append(x.canonize())
+                p = size2pck[size]
+                raw = data_int
+                x = asm_raw(raw)
+                x.element_size = size
+                lines.append(x)
                 continue
             if directive == 'comm':
                 # TODO
                 continue
             if directive == 'split':  # custom command
-                lines.append(asm_raw(line.strip()))
+                x = asm_raw()
+                x.split = True
+                lines.append(x)
                 continue
             if directive == 'dontsplit':  # custom command
                 lines.append(asm_raw(line.strip()))
@@ -168,18 +187,22 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None, gen_label_index=0):
             elif state == 1:
                 # asm_raw
                 if isinstance(lines[i], asm_raw):
-                    if lines[i].raw.startswith('.split'):
+                    if hasattr(lines[i], 'split'):
                         state = 0
                         block_may_link = False
                         i += 1
-                    elif lines[i].raw.startswith('.dontsplit'):
+                    else: #if lines[i].raw.startswith('.dontsplit'):
+                        # raw asm are link by default
                         # print 'dontsplit'
                         state = 1
                         block_may_link = True
+                        b.addline(lines[i])
                         i += 1
+                    """
                     else:
                         b.addline(lines[i])
                         i += 1
+                    """
                 # asm_label
                 elif isinstance(lines[i], asm_label):
                     if block_may_link:
diff --git a/miasm2/core/utils.py b/miasm2/core/utils.py
index 44d1e8e2..ebffd786 100644
--- a/miasm2/core/utils.py
+++ b/miasm2/core/utils.py
@@ -4,11 +4,18 @@ upck8 = lambda x: struct.unpack('B', x)[0]
 upck16 = lambda x: struct.unpack('H', x)[0]
 upck32 = lambda x: struct.unpack('I', x)[0]
 upck64 = lambda x: struct.unpack('Q', x)[0]
+pck8 = lambda x: struct.pack('B', x)
 pck16 = lambda x: struct.pack('H', x)
 pck32 = lambda x: struct.pack('I', x)
 pck64 = lambda x: struct.pack('Q', x)
 
 
+pck = {8:pck8,
+       16:pck16,
+       32:pck32,
+       64:pck64}
+
+
 class Disasm_Exception(Exception):
     pass
 
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index 8313c63c..a7249f78 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -317,7 +317,7 @@ class libimp:
             all_ads = self.lib_imp2dstad[ad].values()
             all_ads = reduce(lambda x, y: x + list(y), all_ads, [])
             all_ads = [x for x in all_ads if filter(x)]
-            # log.debug('%s' % [hex(x) for x in all_ads])
+            log.debug('ads: %s' % [hex(x) for x in all_ads])
             all_ads.sort()
             # first, drop None
             if not all_ads:
@@ -333,12 +333,12 @@ class libimp:
                     i += 1
                 funcs = [out_ads[x] for x in all_ads[:i + 1]]
                 try:
-                    off = e.virt2off(othunk)
+                    rva = e.virt2rva(othunk)
                 except pe.InvalidOffset:
-                    off = None
-                if off is not None:  # e.is_in_virt_address(othunk):
+                    rva = None
+                if rva is not None:  # e.is_in_virt_address(othunk):
                     new_lib.append(({"name": n,
-                                     "firstthunk": off},
+                                     "firstthunk": rva},
                                     funcs)
                                    )
                 all_ads = all_ads[i + 1:]