diff options
Diffstat (limited to 'miasm2/ir/translators')
| -rw-r--r-- | miasm2/ir/translators/C.py | 191 | ||||
| -rw-r--r-- | miasm2/ir/translators/python.py | 3 | ||||
| -rw-r--r-- | miasm2/ir/translators/smt2.py | 31 | ||||
| -rw-r--r-- | miasm2/ir/translators/translator.py | 7 | ||||
| -rw-r--r-- | miasm2/ir/translators/z3_ir.py | 18 |
5 files changed, 170 insertions, 80 deletions
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py index bcffc364..cafec7c8 100644 --- a/miasm2/ir/translators/C.py +++ b/miasm2/ir/translators/C.py @@ -18,44 +18,82 @@ class TranslatorC(Translator): '>>>': 'rot_right', } + def __init__(self, loc_db=None, **kwargs): + """Instance a C translator + @loc_db: LocationDB instance + """ + super(TranslatorC, self).__init__(**kwargs) + # symbol pool + self.loc_db = loc_db + + def _size2mask(self, size): + """Return a C string corresponding to the size2mask operation, with support for + @size <= 128""" + mask = size2mask(size) + if size > 64: + # Avoid "integer constant is too large for its type" error + return "(0x%x | ((uint128_t) 0x%x << 64))" % ( + mask & 0xFFFFFFFFFFFFFFFF, + (mask >> 64) & 0xFFFFFFFFFFFFFFFF, + ) + return "0x%x" % mask def from_ExprId(self, expr): - if isinstance(expr.name, asmblock.AsmLabel): - return "0x%x" % expr.name.offset return str(expr) def from_ExprInt(self, expr): + if expr.size == 128: + # Avoid "integer constant is too large for its type" error + return "(0x%x | ((uint128_t) 0x%x << 64))" % ( + int(expr) & 0xFFFFFFFFFFFFFFFF, + (int(expr) >> 64) & 0xFFFFFFFFFFFFFFFF, + ) return "0x%x" % expr.arg.arg + def from_ExprLoc(self, expr): + loc_key = expr.loc_key + if self.loc_db is None: + return str(loc_key) + + offset = self.loc_db.get_location_offset(loc_key) + if offset is None: + return str(loc_key) + + return "0x%x" % offset + def from_ExprAff(self, expr): - return "%s = %s" % tuple(map(self.from_expr, (expr.dst, expr.src))) + new_dst = self.from_expr(expr.dst) + new_src = self.from_expr(expr.src) + return "%s = %s" % (new_dst, new_src) def from_ExprCond(self, expr): - return "(%s?%s:%s)" % tuple(map(self.from_expr, - (expr.cond, expr.src1, expr.src2))) + new_cond = self.from_expr(expr.cond) + new_src1 = self.from_expr(expr.src1) + new_src2 = self.from_expr(expr.src2) + return "(%s?%s:%s)" % (new_cond, new_src1, new_src2) def from_ExprMem(self, expr): - return "MEM_LOOKUP_%.2d(jitcpu, %s)" % (expr.size, - self.from_expr(expr.arg)) + new_ptr = self.from_expr(expr.arg) + return "MEM_LOOKUP_%.2d(jitcpu, %s)" % (expr.size, new_ptr) def from_ExprOp(self, expr): if len(expr.args) == 1: if expr.op == 'parity': - return "parity(%s&0x%x)" % (self.from_expr(expr.args[0]), - size2mask(expr.args[0].size)) + return "parity(%s&%s)" % ( + self.from_expr(expr.args[0]), + self._size2mask(expr.args[0].size), + ) elif expr.op in ['cntleadzeros', 'cnttrailzeros']: - return "%s(0x%x, %s)" % (expr.op, - expr.args[0].size, - self.from_expr(expr.args[0])) - elif expr.op in ['clz']: - return "%s(%s)" % (expr.op, - self.from_expr(expr.args[0])) + return "%s(0x%x, %s)" % ( + expr.op, + expr.args[0].size, + self.from_expr(expr.args[0]) + ) elif expr.op == '!': - return "(~ %s)&0x%x" % (self.from_expr(expr.args[0]), - size2mask(expr.args[0].size)) - elif expr.op in ["hex2bcd", "bcd2hex"]: - return "%s_%d(%s)" % (expr.op, expr.args[0].size, - self.from_expr(expr.args[0])) + return "(~ %s)&%s" % ( + self.from_expr(expr.args[0]), + self._size2mask(expr.args[0].size), + ) elif (expr.op.startswith("double_to_") or expr.op.endswith("_to_double") or expr.op.startswith("access_") or @@ -63,37 +101,53 @@ class TranslatorC(Translator): expr.op.startswith("fxam_c") or expr.op in ["-", "ftan", "frndint", "f2xm1", "fsin", "fsqrt", "fabs", "fcos", "fchs"]): - return "%s(%s)" % (expr.op, self.from_expr(expr.args[0])) + return "%s(%s)" % ( + expr.op, + self.from_expr(expr.args[0]) + ) else: raise NotImplementedError('Unknown op: %r' % expr.op) elif len(expr.args) == 2: if expr.op == "==": - return '(((%s&0x%x) == (%s&0x%x))?1:0)' % ( - self.from_expr(expr.args[0]), size2mask(expr.args[0].size), - self.from_expr(expr.args[1]), size2mask(expr.args[1].size)) + return '(((%s&%s) == (%s&%s))?1:0)' % ( + self.from_expr(expr.args[0]), + self._size2mask(expr.args[0].size), + self.from_expr(expr.args[1]), + self._size2mask(expr.args[1].size), + ) elif expr.op in self.dct_shift: - return 'SHIFT_%s(%d, %s, %s)' % (self.dct_shift[expr.op].upper(), - expr.args[0].size, - self.from_expr(expr.args[0]), - self.from_expr(expr.args[1])) + return 'SHIFT_%s(%d, %s, %s)' % ( + self.dct_shift[expr.op].upper(), + expr.args[0].size, + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]) + ) elif expr.is_associative() or expr.op in ["%", "/"]: - oper = ['(%s&0x%x)' % (self.from_expr(arg), size2mask(arg.size)) + oper = ['(%s&%s)' % ( + self.from_expr(arg), + self._size2mask(arg.size) + ) for arg in expr.args] oper = str(expr.op).join(oper) - return "((%s)&0x%x)" % (oper, size2mask(expr.args[0].size)) + return "((%s)&%s)" % (oper, self._size2mask(expr.args[0].size)) elif expr.op in ['-']: - return '(((%s&0x%x) %s (%s&0x%x))&0x%x)' % ( - self.from_expr(expr.args[0]), size2mask(expr.args[0].size), + return '(((%s&%s) %s (%s&%s))&%s)' % ( + self.from_expr(expr.args[0]), + self._size2mask(expr.args[0].size), str(expr.op), - self.from_expr(expr.args[1]), size2mask(expr.args[1].size), - size2mask(expr.args[0].size)) + self.from_expr(expr.args[1]), + self._size2mask(expr.args[1].size), + self._size2mask(expr.args[0].size) + ) elif expr.op in self.dct_rot: - return '(%s(%s, %s, %s) &0x%x)' % (self.dct_rot[expr.op], - expr.args[0].size, - self.from_expr(expr.args[0]), - self.from_expr(expr.args[1]), - size2mask(expr.args[0].size)) + return '(%s(%s, %s, %s) &%s)' % ( + self.dct_rot[expr.op], + expr.args[0].size, + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]), + self._size2mask(expr.args[0].size), + ) elif expr.op == 'x86_cpuid': return "%s(%s, %s)" % (expr.op, self.from_expr(expr.args[0]), @@ -101,38 +155,53 @@ class TranslatorC(Translator): elif (expr.op.startswith("fcom") or expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale", "fprem", "fprem_lsb", "fyl2x", "fpatan"]): - return "fpu_%s(%s, %s)" % (expr.op, - self.from_expr(expr.args[0]), - self.from_expr(expr.args[1])) + return "fpu_%s(%s, %s)" % ( + expr.op, + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]) + ) elif expr.op == "segm": return "segm2addr(jitcpu, %s, %s)" % ( - self.from_expr(expr.args[0]), self.from_expr(expr.args[1])) + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]) + ) elif expr.op in ['udiv', 'umod', 'idiv', 'imod']: - return '%s%d((vm_cpu_t*)jitcpu->cpu, %s, %s)' % (expr.op, - expr.args[0].size, - self.from_expr(expr.args[0]), - self.from_expr(expr.args[1])) + return '%s%d(%s, %s)' % ( + expr.op, + expr.args[0].size, + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]) + ) elif expr.op in ["bcdadd", "bcdadd_cf"]: - return "%s_%d(%s, %s)" % (expr.op, expr.args[0].size, - self.from_expr(expr.args[0]), - self.from_expr(expr.args[1])) + return "%s_%d(%s, %s)" % ( + expr.op, expr.args[0].size, + self.from_expr(expr.args[0]), + self.from_expr(expr.args[1]) + ) else: raise NotImplementedError('Unknown op: %r' % expr.op) elif len(expr.args) >= 3 and expr.is_associative(): # ????? - oper = ['(%s&0x%x)' % (self.from_expr(arg), size2mask(arg.size)) + oper = ['(%s&%s)' % ( + self.from_expr(arg), + self._size2mask(arg.size), + ) for arg in expr.args] oper = str(expr.op).join(oper) - return "((%s)&0x%x)" % (oper, size2mask(expr.args[0].size)) - + return "((%s)&%s)" % ( + oper, + self._size2mask(expr.args[0].size) + ) else: raise NotImplementedError('Unknown op: %s' % expr.op) def from_ExprSlice(self, expr): # XXX check mask for 64 bit & 32 bit compat - return "((%s>>%d) & 0x%X)" % (self.from_expr(expr.arg), - expr.start, - (1 << (expr.stop - expr.start)) - 1) + return "((%s>>%d) &%s)" % ( + self.from_expr(expr.arg), + expr.start, + self._size2mask(expr.stop - expr.start) + ) def from_ExprCompose(self, expr): out = [] @@ -149,10 +218,12 @@ class TranslatorC(Translator): dst_cast = "uint%d_t" % size for index, arg in expr.iter_args(): - out.append("(((%s)(%s & 0x%X)) << %d)" % (dst_cast, - self.from_expr(arg), - (1 << arg.size) - 1, - index)) + out.append("(((%s)(%s & %s)) << %d)" % ( + dst_cast, + self.from_expr(arg), + self._size2mask(arg.size), + index) + ) out = ' | '.join(out) return '(' + out + ')' diff --git a/miasm2/ir/translators/python.py b/miasm2/ir/translators/python.py index d7369e9e..e05f5e4d 100644 --- a/miasm2/ir/translators/python.py +++ b/miasm2/ir/translators/python.py @@ -20,6 +20,9 @@ class TranslatorPython(Translator): def from_ExprId(self, expr): return str(expr) + def from_ExprLoc(self, expr): + return str(expr) + def from_ExprMem(self, expr): return "memory(%s, 0x%x)" % (self.from_expr(expr.arg), expr.size / 8) diff --git a/miasm2/ir/translators/smt2.py b/miasm2/ir/translators/smt2.py index 18bcb9bd..1a513bfb 100644 --- a/miasm2/ir/translators/smt2.py +++ b/miasm2/ir/translators/smt2.py @@ -1,7 +1,6 @@ import logging import operator -from miasm2.core.asmblock import AsmLabel from miasm2.ir.translators.translator import Translator from miasm2.expression.smt2_helper import * @@ -120,7 +119,7 @@ class TranslatorSMT2(Translator): # Implemented language __LANG__ = "smt2" - def __init__(self, endianness="<", **kwargs): + def __init__(self, endianness="<", loc_db=None, **kwargs): """Instance a SMT2 translator @endianness: (optional) memory endianness """ @@ -129,24 +128,26 @@ class TranslatorSMT2(Translator): self._mem = SMT2Mem(endianness) # map of translated bit vectors self._bitvectors = dict() + # symbol pool + self.loc_db = loc_db def from_ExprInt(self, expr): return bit_vec_val(expr.arg.arg, expr.size) def from_ExprId(self, expr): - if isinstance(expr.name, AsmLabel): - if expr.name.offset is not None: - return bit_vec_val(str(expr.name.offset), expr.size) - else: - # SMT2-escape expression name - name = "|{}|".format(str(expr.name)) - if name not in self._bitvectors: - self._bitvectors[name] = expr.size - return name - else: - if str(expr) not in self._bitvectors: - self._bitvectors[str(expr)] = expr.size - return str(expr) + if str(expr) not in self._bitvectors: + self._bitvectors[str(expr)] = expr.size + return str(expr) + + def from_ExprLoc(self, expr): + loc_key = expr.loc_key + if self.loc_db is None or self.loc_db.get_location_offset(loc_key) is None: + if str(loc_key) not in self._bitvectors: + self._bitvectors[str(loc_key)] = expr.size + return str(loc_key) + + offset = self.loc_db.get_location_offset(loc_key) + return bit_vec_val(str(offset), expr.size) def from_ExprMem(self, expr): addr = self.from_expr(expr.arg) diff --git a/miasm2/ir/translators/translator.py b/miasm2/ir/translators/translator.py index e3641843..557fdabe 100644 --- a/miasm2/ir/translators/translator.py +++ b/miasm2/ir/translators/translator.py @@ -53,6 +53,12 @@ class Translator(object): """ raise NotImplementedError("Abstract method") + def from_ExprLoc(self, expr): + """Translate an ExprLoc + @expr: ExprLoc to translate + """ + raise NotImplementedError("Abstract method") + def from_ExprCompose(self, expr): """Translate an ExprCompose @expr: ExprCompose to translate @@ -100,6 +106,7 @@ class Translator(object): # Handle Expr type handlers = {m2_expr.ExprInt: self.from_ExprInt, m2_expr.ExprId: self.from_ExprId, + m2_expr.ExprLoc: self.from_ExprLoc, m2_expr.ExprCompose: self.from_ExprCompose, m2_expr.ExprSlice: self.from_ExprSlice, m2_expr.ExprOp: self.from_ExprOp, diff --git a/miasm2/ir/translators/z3_ir.py b/miasm2/ir/translators/z3_ir.py index 536daff1..887c68d0 100644 --- a/miasm2/ir/translators/z3_ir.py +++ b/miasm2/ir/translators/z3_ir.py @@ -5,7 +5,6 @@ import operator # Raise an ImportError if z3 is not available WITHOUT actually importing it imp.find_module("z3") -from miasm2.core.asmblock import AsmLabel from miasm2.ir.translators.translator import Translator log = logging.getLogger("translator_z3") @@ -116,7 +115,7 @@ class TranslatorZ3(Translator): # Operations translation trivial_ops = ["+", "-", "/", "%", "&", "^", "|", "*", "<<"] - def __init__(self, endianness="<", **kwargs): + def __init__(self, endianness="<", loc_db=None, **kwargs): """Instance a Z3 translator @endianness: (optional) memory endianness """ @@ -126,15 +125,24 @@ class TranslatorZ3(Translator): super(TranslatorZ3, self).__init__(**kwargs) self._mem = Z3Mem(endianness) + self.loc_db = loc_db def from_ExprInt(self, expr): return z3.BitVecVal(expr.arg.arg, expr.size) def from_ExprId(self, expr): - if isinstance(expr.name, AsmLabel) and expr.name.offset is not None: - return z3.BitVecVal(expr.name.offset, expr.size) - else: + return z3.BitVec(str(expr), expr.size) + + def from_ExprLoc(self, expr): + if self.loc_db is None: + # No loc_db, fallback to default name return z3.BitVec(str(expr), expr.size) + loc_key = expr.loc_key + offset = self.loc_db.get_location_offset(loc_key) + if offset is not None: + return z3.BitVecVal(offset, expr.size) + # fallback to default name + return z3.BitVec(str(loc_key), expr.size) def from_ExprMem(self, expr): addr = self.from_expr(expr.arg) |