diff options
| author | serpilliere <devnull@localhost> | 2011-07-27 11:12:04 +0200 |
|---|---|---|
| committer | serpilliere <devnull@localhost> | 2011-07-27 11:12:04 +0200 |
| commit | 066972d7f1e30792256c137ad2417a0adaee7753 (patch) | |
| tree | c2d020ed21b556e8e5c926aa2dc97ce34dc4885a /miasm/expression/expression_helper.py | |
| download | focaccia-miasm-066972d7f1e30792256c137ad2417a0adaee7753.tar.gz focaccia-miasm-066972d7f1e30792256c137ad2417a0adaee7753.zip | |
realease commit
Diffstat (limited to 'miasm/expression/expression_helper.py')
| -rw-r--r-- | miasm/expression/expression_helper.py | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/miasm/expression/expression_helper.py b/miasm/expression/expression_helper.py new file mode 100644 index 00000000..c6bcfa8e --- /dev/null +++ b/miasm/expression/expression_helper.py @@ -0,0 +1,646 @@ +# +# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +from miasm.expression.expression import * + +tab_size_int = {8:uint8, + 16:uint16, + 32:uint32, + 64:uint64, + } + +tab_max_uint = {8:uint8(0xFF), 16:uint16(0xFFFF), 32:uint32(0xFFFFFFFF), 64:uint64(0xFFFFFFFFFFFFFFFFL)} + + +def parity(self, a): + tmp = (a)&0xFFL + cpt = 1 + while tmp!=0: + cpt^=tmp&1 + tmp>>=1 + return cpt + +def merge_sliceto_slice(args): + sources = {} + non_slice = {} + sources_int = {} + for a in args: + if isinstance(a.arg, ExprInt): + sources_int[a.start] = a + elif isinstance(a.arg, ExprSlice): + if not a.arg.arg in sources: + sources[a.arg.arg] = [] + sources[a.arg.arg].append(a) + else: + non_slice[a.start] = a + + + #find max stop to determine size + max_size = None + for a in args: + if max_size == None or max_size < a.stop: + max_size = a.stop + + + + #first simplify all num slices + + final_sources = [] + sorted_s = [] + for x in sources_int.values(): + #mask int + v = x.arg.arg & ((1<<(x.stop-x.start))-1) + x.arg.arg = v + sorted_s.append((x.start, x)) + sorted_s.sort() + while sorted_s: + + start, v = sorted_s.pop() + out = expr_replace(v, {}) + + + while sorted_s: + if sorted_s[-1][1].stop != start: + break + + start = sorted_s[-1][1].start + + a = uint64((int(out.arg.arg) << (out.start - start )) + sorted_s[-1][1].arg.arg) + out.arg = ExprInt(uint32(a)) + sorted_s.pop() + out.start = start + + out_type = tab_size_int[max_size] + out.arg.arg = out_type(out.arg.arg) + final_sources.append((start, out)) + + final_sources_int = final_sources + + #check if same sources have corresponding start/stop + #is slice AND is sliceto + simp_sources = [] + for s, args in sources.items(): + final_sources = [] + sorted_s = [] + for x in args: + sorted_s.append((x.start, x)) + sorted_s.sort() + while sorted_s: + start, v = sorted_s.pop() + out = expr_replace(v, {}) + while sorted_s: + if sorted_s[-1][1].stop != start: + break + if sorted_s[-1][1].arg.stop != out.arg.start: + break + + start = sorted_s[-1][1].start + out.arg.start = sorted_s[-1][1].arg.start + sorted_s.pop() + out.start = start + + final_sources.append((start, out)) + + simp_sources+=final_sources + + simp_sources+= final_sources_int + + for i, v in non_slice.items(): + simp_sources.append((i, v)) + + simp_sources.sort() + + simp_sources = [x[1] for x in simp_sources] + return simp_sources + + +def expr_simp(e): + if e.is_simp: + return e + e = expr_simp_w(e) + e.is_simp = True + return e + +def expr_simp_w(e): + if isinstance(e, ExprTop): + return e + if isinstance(e, ExprInt): + return e + elif isinstance(e, ExprId): + return e + elif isinstance(e, ExprAff): + return ExprAff(expr_simp(e.dst), expr_simp(e.src)) + elif isinstance(e, ExprCond): + c = expr_simp(e.cond) + if isinstance(c, ExprInt): + print e + fdsfsdf + if c == 0: + return expr_simp(e.src2) + else: + return expr_simp(e.src1) + + return ExprCond(expr_simp(e.cond), expr_simp(e.src1), expr_simp(e.src2)) + elif isinstance(e, ExprMem): + if isinstance(e.arg, ExprTop): + return ExprTop() + return ExprMem(expr_simp(e.arg), size = e.size) + elif isinstance(e, ExprOp): + op, args = e.op, list(e.args) + if ExprTop() in args: + return ExprTop() + #int OP int => int + if e.op in ['+', '-', '*', '|', '&', '^', '>>', '<<'] and isinstance(args[0], ExprInt) and isinstance(args[1], ExprInt) : + if args[0].get_size() != args[1].get_size(): + raise ValueError("diff size! %s"%(str(e))) + if e.op == '+': + o = args[0].arg + args[1].arg + elif e.op == '-': + o = args[0].arg - args[1].arg + elif e.op == '*': + o = args[0].arg * args[1].arg + elif e.op == '|': + o = args[0].arg | args[1].arg + elif e.op == '&': + o = args[0].arg & args[1].arg + elif e.op == '^': + o = args[0].arg ^ args[1].arg + elif e.op == '>>': + o = args[0].arg >> args[1].arg + elif e.op == '<<': + o = args[0].arg << args[1].arg + else: + raise ValueError("zarb op %s"%str(e)) + z = ExprInt(tab_size_int[args[0].get_size()](o)) + return z + + #int OP xx => xx OP int + if e.op in ['+', '*', '|', '&', '^']: + if isinstance(e.args[0], ExprInt) and not isinstance(e.args[1], ExprInt): + op, args= e.op, [e.args[1], e.args[0]] + #A+0 =>A + if op in ['+', '-', '|', "^", "<<", ">>"]: + if isinstance(args[0], ExprInt) and args[0].arg == 0 and not op in ['-', "<<", ">>"]: + return expr_simp(args[1]) + if isinstance(args[1], ExprInt) and args[1].arg == 0: + return expr_simp(args[0]) + + #A&0 =>0 + if op in ['&']: + if isinstance(args[1], ExprInt) and args[1].arg == 0: + return args[1] + + #A-(-123) =>A+123 + if op == '-' and isinstance(args[1], ExprInt) and int32(args[1].arg)<0 : + op = '+' + args[1] = ExprInt(-args[1].arg) + + #A+(-123) =>A-123 + if op == '+' and isinstance(args[1], ExprInt) and int32(args[1].arg)<0 : + op = '-' + args[1] = ExprInt(-args[1].arg) + #fdsfs + #A+3+2 => A+5 + if op in ['+', '-'] and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt): + op1 = op + op2 = args[0].op + if op1 == op2: + op = op1 + args1 = args[0].args[1].arg + args[1].arg + else: + op = op2 + args1 = args[0].args[1].arg - args[1].arg + + + #if op == '-': + # args1 = -args1 + args0 = args[0].args[0] + args = [args0, ExprInt(args1)] + + #0 - (a-b) => b-a + if op == '-' and isinstance(args[0], ExprInt) and args[0].arg == 0 and isinstance(args[1], ExprOp) and args[1].op == "-": + return expr_simp(args[1].args[1] - args[1].args[0]) + + #a<<< x <<< y => a <<< (x+y) (ou <<< >>>) + if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op in ['<<<', '>>>'] and isinstance(args[0].args[1], ExprInt): + op1 = op + op2 = args[0].op + if op1 == op2: + op = op1 + args1 = args[0].args[1].arg + args[1].arg + else: + op = op2 + args1 = args[0].args[1].arg - args[1].arg + + args0 = args[0].args[0] + args = [args0, ExprInt(args1)] + + + #a >>> 0 => a (ou <<<) + if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and args[1].arg == 0: + e = expr_simp(args[0]) + return e + + #((a >>> b) <<< b) => a + if op in ['<<<', '>>>'] and isinstance(args[0], ExprOp) and args[0].op in ['<<<', '>>>'] and args[1] == args[0].args[1]: + oo = op, args[0].op + if oo in [('<<<', '>>>'), ('>>>', '<<<')]: + + e = expr_simp(args[0].args[0]) + return e + + + #( a + int1 ) - (b+int2) => a - (b+ (int1-int2)) + if op in ['+', '-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[1], ExprOp) and args[1].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt) and isinstance(args[1].args[1], ExprInt): + op1 = op + op2 = args[0].op + op3 = args[1].op + + if op1 == op2: + m_op = "+" + else: + m_op = "-" + e = ExprOp(op1, + args[0].args[0], + ExprOp(m_op, + ExprOp(op3, + args[1].args[0], + args[1].args[1] + ), + args[0].args[1] + ) + ) + e = expr_simp(e) + + return e + + #(a - (a + XXX)) => 0-XXX + if op in ['-'] and isinstance(args[1], ExprOp) and args[1].op in ['+', '-'] and args[1].args[0] == args[0]: + if op == args[1].op: + m_op = "+" + else: + m_op = "-" + + z = ExprInt(tab_size_int[args[1].args[1].get_size()](0)) + e = ExprOp(m_op, + z, + args[1].args[1]) + e = expr_simp(e) + + return e + + + #((a +- XXX) -a) => 0+-XXX + if op in ['-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and args[0].args[0] == args[1]: + m_op = args[0].op + + z = ExprInt(tab_size_int[args[0].args[1].get_size()](0)) + e = ExprOp(m_op, + z, + args[0].args[1]) + e = expr_simp(e) + + return e + + # ((a ^ b) ^ a) => b (or commut) + if op in ['^'] and isinstance(args[0], ExprOp) and args[0].op in ['^']: + rest_a = None + if args[0].args[0] == args[1]: + rest_a = args[0].args[1] + elif args[0].args[1] == args[1]: + rest_a = args[0].args[0] + if rest_a != None: + e = expr_simp(rest_a) + return e + # (a ^ (a ^ b) ) => b (or commut) + if op in ['^'] and isinstance(args[1], ExprOp) and args[1].op in ['^']: + rest_a = None + if args[1].args[0] == args[0]: + rest_a = args[1].args[1] + elif args[1].args[1] == args[0]: + rest_a = args[1].args[0] + if rest_a != None: + e = expr_simp(rest_a) + return e + + + # ((a + b) - b) => a (or commut) + if op in ['-'] and isinstance(args[0], ExprOp) and args[0].op in ['+']: + rest_a = None + if args[0].args[1] == args[1]: + rest_a = args[0].args[0] + e = expr_simp(rest_a) + return e + + # ((a - b) + b) => a (or commut) + if op in ['+'] and isinstance(args[0], ExprOp) and args[0].op in ['-']: + rest_a = None + if args[0].args[1] == args[1]: + rest_a = args[0].args[0] + e = expr_simp(rest_a) + return e + + # a<<< a.size => a + if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and args[1].arg == args[0].get_size(): + return expr_simp(args[0]) + + #!!a => a + if op == '!' and isinstance(args[0], ExprOp) and args[0].op == '!': + new_e = args[0].args[0] + return expr_simp(new_e) + + #! (!X + int) => X - int + if op == '!' and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[0].args[0], ExprOp) and args[0].args[0].op == '!': + if args[0].op == '+': + op = '-' + else: + op = '+' + return expr_simp(ExprOp(op, args[0].args[0].args[0], args[0].args[1])) + + # ((a (op1+-) int) (op2+-) b) => ((a (op2) b) op1 int)) + if op in ['+', '-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and not isinstance(args[1], ExprInt) and args[0].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt): + op1 = op + op2 = args[0].op + e = ExprOp(op2, + ExprOp(op1, + args[0].args[0], + args[1]) + , + args[0].args[1]) + return expr_simp(e) + + + if op == "&" and isinstance(args[0], ExprOp) and args[0].op == '!' and isinstance(args[1], ExprOp) and args[1].op == '!' and isinstance(args[0].args[0], ExprOp) and args[0].args[0].op == '&' and isinstance(args[1].args[0], ExprOp) and args[1].args[0].op == '&': + + ##############1 + a1 = args[0].args[0].args[0] + if isinstance(a1, ExprOp) and a1.op == '!': + a1 = a1.args[0] + elif isinstance(a1, ExprInt): + a1 = ExprInt(~a1.arg) + else: + a1 = None + + b1 = args[0].args[0].args[1] + if isinstance(b1, ExprOp) and b1.op == '!': + b1 = b1.args[0] + elif isinstance(b1, ExprInt): + b1 = ExprInt(~b1.arg) + else: + b1 = None + + + a2 = args[1].args[0].args[0] + b2 = args[1].args[0].args[1] + + + if a1 != None and b1 != None and a1 == a2 and b1 == b2: + new_e = ExprOp('^', a1, b1) + return expr_simp(new_e) + + ################2 + a1 = args[1].args[0].args[0] + if isinstance(a1, ExprOp) and a1.op == '!': + a1 = a1.args[0] + elif isinstance(a1, ExprInt): + a1 = ExprInt(~a1.arg) + else: + a1 = None + + b1 = args[1].args[0].args[1] + if isinstance(b1, ExprOp) and b1.op == '!': + b1 = b1.args[0] + elif isinstance(b1, ExprInt): + b1 = ExprInt(~b1.arg) + else: + b1 = None + + + a2 = args[0].args[0].args[0] + b2 = args[0].args[0].args[1] + + + if a1 != None and b1 != None and a1 == a2 and b1 == b2: + new_e = ExprOp('^', a1, b1) + return expr_simp(new_e) + + + # (x & mask) >> shift whith mask < 2**shift => 0 + if op == ">>" and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op == "&": + if isinstance(args[0].args[1], ExprInt) and 2**args[1].arg >= args[0].args[1].arg: + return ExprInt(tab_size_int[args[0].get_size()](0)) + + #! (compose a b c) => (compose !a !b !c) + if op == '!' and isinstance(args[0], ExprCompose): + args = [ExprSliceTo(ExprOp('!', x.arg), x.start, x.stop) for x in args[0].args] + new_e = ExprCompose(args) + return expr_simp(new_e) + #!a[0:X] => (!a)[0:X] + if op == '!' and isinstance(args[0], ExprSlice): + new_e = ExprSlice(ExprOp('!', args[0].arg), args[0].start, args[0].stop) + return expr_simp(new_e) + + + #! int + if op == '!' and isinstance(args[0], ExprInt): + a = args[0] + e = ExprInt(tab_max_uint[a.get_size()]^a.arg) + return e + + #a^a=>0 | a-a =>0 + if op in ['^', '-'] and args[0] == args[1]: + tmp = ExprInt(tab_size_int[args[0].get_size()](0)) + return tmp + + #a & a => a or a | a => a + if op in ['&', '|'] and args[0] == args[1]: + return expr_simp(args[0]) + # int == int => 0 or 1 + if op == '==' and isinstance(args[0], ExprInt) and isinstance(args[1], ExprInt): + if args[0].arg == args[1].arg: + return ExprInt(tab_size_int[args[0].get_size()](1)) + else: + return ExprInt(tab_size_int[args[0].get_size()](0)) + #( a|int == 0) => 0 wirh int != 0 + if op == '==' and isinstance(args[1], ExprInt) and args[1].arg ==0 : + if isinstance(args[0], ExprOp) and args[0].op == '|' and isinstance(args[0].args[1], ExprInt) and \ + args[0].args[1].arg != 0: + return ExprInt(tab_size_int[args[0].get_size()](0)) + + + if op == 'parity' and isinstance(args[0], ExprInt): + fsdfsdf + return ExprInt(tab_size_int[args[0].get_size()](parity(args[0].arg))) + + new_e = ExprOp(op, *[expr_simp(x) for x in args]) + if new_e == e: + return new_e + else: + return expr_simp(new_e) + + #Slice(int) => new_int + elif isinstance(e, ExprSlice): + arg = expr_simp(e.arg) + + if isinstance(arg, ExprTop): + return ExprTop() + elif e.start == 0 and e.stop == 32 and arg.get_size() == 32: + return arg + + elif isinstance(arg, ExprInt): + total_bit = e.stop-e.start + mask = uint64((uint64(1)<<(e.stop-e.start))-1) + if total_bit in tab_size_int: + return ExprInt(tab_size_int[total_bit]((uint64((arg.arg)>>e.start)) & mask)) + else: + return ExprInt(type(arg.arg)((uint64((arg.arg)>>e.start)) & mask)) + elif isinstance(arg, ExprSlice): + if e.stop-e.start > arg.stop-arg.start: + raise ValueError('slice in slice: getting more val', str(e)) + + new_e = ExprSlice(expr_simp(arg.arg), e.start + arg.start, e.start + arg.start + (e.stop - e.start)) + return expr_simp(new_e) + elif isinstance(arg, ExprCompose): + for a in arg.args: + if a.start <= e.start and a.stop>=e.stop: + new_e = a.arg[e.start-a.start:e.stop-a.start] + new_e = expr_simp(new_e) + return new_e + elif isinstance(arg, ExprOp) and e.start == 0: + #if (op ..)[0:X] and op result is good size, skip slice + if e.stop == arg.get_size(): + return expr_simp(arg) + return ExprSlice(arg, e.start, e.stop) + elif isinstance(arg, ExprMem) and e.start == 0 and arg.size == e.stop: + e = expr_simp(arg) + return e + #XXXX hum, is it safe? + elif isinstance(arg, ExprMem) and e.start == 0 and arg.size > e.stop and e.stop %8 == 0: + e = expr_simp(ExprMem(e.arg.arg, size = e.stop)) + return e + + + + + return ExprSlice(arg, e.start, e.stop) + elif isinstance(e, ExprSliceTo): + if isinstance(e.arg, ExprTop): + return ExprTop() + if isinstance(e.arg, ExprSlice) and e.arg.start == 0: + return expr_simp(ExprSliceTo(expr_simp(e.arg.arg), e.start, e.stop)) + + #(.., a[0:X], ..) _to[Y:Z] with X > Z-Y => a[0:X]_to[Y:Z] + if isinstance(e.arg, ExprCompose) and len(e.arg.args) >1: + s = e.get_size() + for a in e.arg.args: + if a.start == 0 and a.stop >= s: + return expr_simp(ExprSliceTo(ExprCompose([a]), e.start, e.stop)) + + + + return ExprSliceTo(expr_simp(e.arg), e.start, e.stop) + elif isinstance(e, ExprCompose): + #(.., a_to[x:y], a[:]_to[y:z], ..) => (.., a[x:z], ..) + e = ExprCompose([expr_simp(x) for x in e.args]) + args = [] + i = -1 + simp = False + while i+1 < len(e.args): + i+=1 + if not args: + args.append(e.args[i]) + continue + if args[-1].stop != e.args[i].start: + continue + if not isinstance(e.args[i].arg, ExprSlice): + continue + if isinstance(args[-1].arg, ExprSlice): + a = args[-1] + else: + a = ExprSliceTo(ExprSlice(args[-1].arg, 0, args[-1].arg.get_size()), args[-1].start, args[-1].stop) + if a.arg.arg != e.args[i].arg.arg: + continue + if a.stop != e.args[i].start: + continue + args[-1] = ExprSliceTo(e.args[i].arg.arg, a.start, e.args[i].stop) + simp = True + + if simp: + return expr_simp(ExprCompose(args)) + + + + all_top = True + for a in e.args: + if not isinstance(a, ExprTop): + all_top = False + break + if all_top: + return ExprTop() + if ExprTop() in e.args: + return ExprTop() + + args = merge_sliceto_slice(e.args) + if len(args) == 1: + a = args[0] + if isinstance(a.arg, ExprInt): + if a.arg.get_size() != a.stop: + print a, a.arg.get_size(), a.stop + raise ValueError("cast in compose!", e) + return a.arg + + uu = expr_simp(a.arg) + return uu + if len(args) != len(e.args): + return expr_simp(ExprCompose(args)) + else: + return ExprCompose(args) + + else: + raise 'bad expr' + + +def expr_cmp(e1, e2): + return str(e1) == str(e2) + +#replace id by another in expr +def expr_replace(e, repl): + if isinstance(e, ExprInt): + return e + elif isinstance(e, ExprId): + if e in repl: + return repl[e] + return e + elif isinstance(e, ExprAff): + return ExprAff(expr_replace(e.dst, repl), expr_replace(e.src, repl)) + elif isinstance(e, ExprCond): + return ExprCond(expr_replace(e.cond, repl), expr_replace(e.src1, repl), expr_replace(e.src2, repl)) + elif isinstance(e, ExprMem): + return ExprMem(expr_replace(e.arg, repl), size = e.size) + elif isinstance(e, ExprOp): + return ExprOp(e.op, *[expr_replace(x, repl) for x in e.args]) + elif isinstance(e, ExprSlice): + return ExprSlice(expr_replace(e.arg, repl), e.start, e.stop) + elif isinstance(e, ExprSliceTo): + return ExprSliceTo(expr_replace(e.arg, repl), e.start, e.stop) + elif isinstance(e, ExprCompose): + return ExprCompose([expr_replace(x, repl) for x in e.args]) + else: + raise 'bad expr' + + + |