about summary refs log tree commit diff stats
path: root/miasm2/core
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/core')
-rw-r--r--miasm2/core/asmbloc.py42
-rw-r--r--miasm2/core/cpu.py8
-rw-r--r--miasm2/core/parse_asm.py67
3 files changed, 88 insertions, 29 deletions
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..41e5b4f6 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:
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: