diff options
Diffstat (limited to 'miasm2')
| -rw-r--r-- | miasm2/arch/arm/arch.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/sh4/arch.py | 3 | ||||
| -rw-r--r-- | miasm2/core/asmbloc.py | 42 | ||||
| -rw-r--r-- | miasm2/core/cpu.py | 11 | ||||
| -rw-r--r-- | miasm2/core/parse_asm.py | 67 | ||||
| -rw-r--r-- | miasm2/core/utils.py | 7 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 10 |
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:] |