diff options
| -rw-r--r-- | miasm2/core/asmbloc.py | 42 | ||||
| -rw-r--r-- | miasm2/core/cpu.py | 8 | ||||
| -rw-r--r-- | miasm2/core/parse_asm.py | 67 |
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: |