diff options
Diffstat (limited to 'miasm/ir/ir.py')
| -rw-r--r-- | miasm/ir/ir.py | 1052 |
1 files changed, 0 insertions, 1052 deletions
diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py deleted file mode 100644 index 57bff4db..00000000 --- a/miasm/ir/ir.py +++ /dev/null @@ -1,1052 +0,0 @@ -#-*- coding:utf-8 -*- - -# -# Copyright (C) 2013 Fabrice Desclaux -# -# 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 builtins import zip -import warnings - -from itertools import chain -from future.utils import viewvalues, viewitems - -import miasm.expression.expression as m2_expr -from miasm.expression.expression_helper import get_missing_interval -from miasm.core.asmblock import AsmBlock, AsmBlockBad, AsmConstraint -from miasm.core.graph import DiGraph -from miasm.ir.translators import Translator -from functools import reduce -from miasm.core import utils -import re - - -def _expr_loc_to_symb(expr, loc_db): - if not expr.is_loc(): - return expr - if loc_db is None: - name = str(expr) - else: - names = loc_db.get_location_names(expr.loc_key) - if not names: - name = loc_db.pretty_str(expr.loc_key) - else: - # Use only one name for readability - name = sorted(names)[0] - return m2_expr.ExprId(name, expr.size) - - -ESCAPE_CHARS = re.compile('[' + re.escape('{}[]') + '&|<>' + ']') - -class TranslatorHtml(Translator): - __LANG__ = "custom_expr_color" - - @staticmethod - def _fix_chars(token): - return "&#%04d;" % ord(token.group()) - - def __init__(self, loc_db=None, **kwargs): - super(TranslatorHtml, self).__init__(**kwargs) - self.loc_db = loc_db - - def str_protected_child(self, child, parent): - return ("(%s)" % ( - self.from_expr(child)) if m2_expr.should_parenthesize_child(child, parent) - else self.from_expr(child) - ) - - def from_ExprInt(self, expr): - out = str(expr) - out = '<font color="%s">%s</font>' % (utils.COLOR_INT, out) - return out - - def from_ExprId(self, expr): - out = str(expr) - out = '<font color="%s">%s</font>' % (utils.COLOR_ID, out) - return out - - def from_ExprLoc(self, expr): - - if self.loc_db is None: - name = ESCAPE_CHARS.sub(self._fix_chars, str((expr))) - else: - names = self.loc_db.get_location_names(expr.loc_key) - if not names: - name = self.loc_db.pretty_str(expr.loc_key) - else: - # Use only one name for readability - name = sorted(names)[0] - name = ESCAPE_CHARS.sub(self._fix_chars, name) - out = '<font color="%s">%s</font>' % (utils.COLOR_LOC, name) - return out - - def from_ExprMem(self, expr): - ptr = self.from_expr(expr.ptr) - size = '@' + str(expr.size) - size = '<font color="%s">%s</font>' % (utils.COLOR_MEM, size) - bracket_left = ESCAPE_CHARS.sub(self._fix_chars, '[') - bracket_right = ESCAPE_CHARS.sub(self._fix_chars, ']') - out = '%s%s%s%s' % (size, bracket_left, ptr, bracket_right) - return out - - def from_ExprSlice(self, expr): - base = self.from_expr(expr.arg) - start = str(expr.start) - stop = str(expr.stop) - bracket_left = ESCAPE_CHARS.sub(self._fix_chars, '[') - bracket_right = ESCAPE_CHARS.sub(self._fix_chars, ']') - out = "(%s)%s%s:%s%s" % (base, bracket_left, start, stop, bracket_right) - return out - - def from_ExprCompose(self, expr): - out = ESCAPE_CHARS.sub(self._fix_chars, "{") - out += ", ".join(["%s, %s, %s" % (self.from_expr(subexpr), - str(idx), - str(idx + subexpr.size)) - for idx, subexpr in expr.iter_args()]) - out += ESCAPE_CHARS.sub(self._fix_chars, "}") - return out - - def from_ExprCond(self, expr): - cond = self.str_protected_child(expr.cond, expr) - src1 = self.from_expr(expr.src1) - src2 = self.from_expr(expr.src2) - out = "%s?(%s,%s)" % (cond, src1, src2) - return out - - def from_ExprOp(self, expr): - op = ESCAPE_CHARS.sub(self._fix_chars, expr._op) - if expr._op == '-': # Unary minus - return '-' + self.str_protected_child(expr._args[0], expr) - if expr.is_associative() or expr.is_infix(): - return (' ' + op + ' ').join([self.str_protected_child(arg, expr) - for arg in expr._args]) - - op = '<font color="%s">%s</font>' % (utils.COLOR_OP_FUNC, op) - return (op + '(' + - ', '.join( - self.from_expr(arg) - for arg in expr._args - ) + ')') - - def from_ExprAssign(self, expr): - return "%s = %s" % tuple(map(expr.from_expr, (expr.dst, expr.src))) - - -def color_expr_html(expr, loc_db): - translator = TranslatorHtml(loc_db=loc_db) - return translator.from_expr(expr) - -def slice_rest(expr): - "Return the completion of the current slice" - size = expr.arg.size - if expr.start >= size or expr.stop > size: - raise ValueError('bad slice rest %s %s %s' % - (size, expr.start, expr.stop)) - - if expr.start == expr.stop: - return [(0, size)] - - rest = [] - if expr.start != 0: - rest.append((0, expr.start)) - if expr.stop < size: - rest.append((expr.stop, size)) - - return rest - - - -class AssignBlock(object): - """Represent parallel IR assignment, such as: - EAX = EBX - EBX = EAX - - -> Exchange between EBX and EAX - - AssignBlock can be seen as a dictionary where keys are the destinations - (ExprId or ExprMem), and values their corresponding sources. - - Also provides common manipulation on this assignments. - - """ - __slots__ = ["_assigns", "_instr"] - - def __init__(self, irs=None, instr=None): - """Create a new AssignBlock - @irs: (optional) sequence of ExprAssign, or dictionary dst (Expr) -> src - (Expr) - @instr: (optional) associate an instruction with this AssignBlock - - """ - if irs is None: - irs = [] - self._instr = instr - self._assigns = {} # ExprAssign.dst -> ExprAssign.src - - # Concurrent assignments are handled in _set - if hasattr(irs, "items"): - for dst, src in viewitems(irs): - self._set(dst, src) - else: - for expraff in irs: - self._set(expraff.dst, expraff.src) - - @property - def instr(self): - """Return the associated instruction, if any""" - return self._instr - - def _set(self, dst, src): - """ - Special cases: - * if dst is an ExprSlice, expand it to assign the full Expression - * if dst already known, sources are merged - """ - if dst.size != src.size: - raise RuntimeError( - "sanitycheck: args must have same size! %s" % - ([(str(arg), arg.size) for arg in [dst, src]])) - - if isinstance(dst, m2_expr.ExprSlice): - # Complete the source with missing slice parts - new_dst = dst.arg - rest = [(m2_expr.ExprSlice(dst.arg, r[0], r[1]), r[0], r[1]) - for r in slice_rest(dst)] - all_a = [(src, dst.start, dst.stop)] + rest - all_a.sort(key=lambda x: x[1]) - args = [expr for (expr, _, _) in all_a] - new_src = m2_expr.ExprCompose(*args) - else: - new_dst, new_src = dst, src - - if new_dst in self._assigns and isinstance(new_src, m2_expr.ExprCompose): - if not isinstance(self[new_dst], m2_expr.ExprCompose): - # prev_RAX = 0x1122334455667788 - # input_RAX[0:8] = 0x89 - # final_RAX -> ? (assignment are in parallel) - raise RuntimeError("Concurrent access on same bit not allowed") - - # Consider slice grouping - expr_list = [(new_dst, new_src), - (new_dst, self[new_dst])] - # Find collision - e_colision = reduce(lambda x, y: x.union(y), - (self.get_modified_slice(dst, src) - for (dst, src) in expr_list), - set()) - - # Sort interval collision - known_intervals = sorted([(x[1], x[2]) for x in e_colision]) - - for i, (_, stop) in enumerate(known_intervals[:-1]): - if stop > known_intervals[i + 1][0]: - raise RuntimeError( - "Concurrent access on same bit not allowed") - - # Fill with missing data - missing_i = get_missing_interval(known_intervals, 0, new_dst.size) - remaining = ((m2_expr.ExprSlice(new_dst, *interval), - interval[0], - interval[1]) - for interval in missing_i) - - # Build the merging expression - args = list(e_colision.union(remaining)) - args.sort(key=lambda x: x[1]) - starts = [start for (_, start, _) in args] - assert len(set(starts)) == len(starts) - args = [expr for (expr, _, _) in args] - new_src = m2_expr.ExprCompose(*args) - - # Sanity check - if not isinstance(new_dst, (m2_expr.ExprId, m2_expr.ExprMem)): - raise TypeError("Destination cannot be a %s" % type(new_dst)) - - self._assigns[new_dst] = new_src - - def __setitem__(self, dst, src): - raise RuntimeError('AssignBlock is immutable') - - def __getitem__(self, key): - return self._assigns[key] - - def __contains__(self, key): - return key in self._assigns - - def iteritems(self): - for dst, src in viewitems(self._assigns): - yield dst, src - - def items(self): - return [(dst, src) for dst, src in viewitems(self._assigns)] - - def itervalues(self): - for src in viewvalues(self._assigns): - yield src - - def keys(self): - return list(self._assigns) - - def values(self): - return list(viewvalues(self._assigns)) - - def __iter__(self): - for dst in self._assigns: - yield dst - - def __delitem__(self, _): - raise RuntimeError('AssignBlock is immutable') - - def update(self, _): - raise RuntimeError('AssignBlock is immutable') - - def __eq__(self, other): - if set(self.keys()) != set(other.keys()): - return False - return all(other[dst] == src for dst, src in viewitems(self)) - - def __ne__(self, other): - return not self == other - - def __len__(self): - return len(self._assigns) - - def get(self, key, default): - return self._assigns.get(key, default) - - @staticmethod - def get_modified_slice(dst, src): - """Return an Expr list of extra expressions needed during the - object instantiation""" - if not isinstance(src, m2_expr.ExprCompose): - raise ValueError("Get mod slice not on expraff slice", str(src)) - modified_s = [] - for index, arg in src.iter_args(): - if not (isinstance(arg, m2_expr.ExprSlice) and - arg.arg == dst and - index == arg.start and - index+arg.size == arg.stop): - # If x is not the initial expression - modified_s.append((arg, index, index+arg.size)) - return modified_s - - def get_w(self): - """Return a set of elements written""" - return set(self.keys()) - - def get_rw(self, mem_read=False, cst_read=False): - """Return a dictionary associating written expressions to a set of - their read requirements - @mem_read: (optional) mem_read argument of `get_r` - @cst_read: (optional) cst_read argument of `get_r` - """ - out = {} - for dst, src in viewitems(self): - src_read = src.get_r(mem_read=mem_read, cst_read=cst_read) - if isinstance(dst, m2_expr.ExprMem) and mem_read: - # Read on destination happens only with ExprMem - src_read.update(dst.ptr.get_r(mem_read=mem_read, - cst_read=cst_read)) - out[dst] = src_read - return out - - def get_r(self, mem_read=False, cst_read=False): - """Return a set of elements reads - @mem_read: (optional) mem_read argument of `get_r` - @cst_read: (optional) cst_read argument of `get_r` - """ - return set( - chain.from_iterable( - viewvalues( - self.get_rw( - mem_read=mem_read, - cst_read=cst_read - ) - ) - ) - ) - - def __str__(self): - out = [] - for dst, src in sorted(viewitems(self._assigns)): - out.append("%s = %s" % (dst, src)) - return "\n".join(out) - - def dst2ExprAssign(self, dst): - """Return an ExprAssign corresponding to @dst equation - @dst: Expr instance""" - return m2_expr.ExprAssign(dst, self[dst]) - - def simplify(self, simplifier): - """ - Return a new AssignBlock with expression simplified - - @simplifier: ExpressionSimplifier instance - """ - new_assignblk = {} - for dst, src in viewitems(self): - if dst == src: - continue - new_src = simplifier(src) - new_dst = simplifier(dst) - new_assignblk[new_dst] = new_src - return AssignBlock(irs=new_assignblk, instr=self.instr) - - def to_string(self, loc_db=None): - out = [] - for dst, src in viewitems(self): - new_src = src.visit(lambda expr:_expr_loc_to_symb(expr, loc_db)) - new_dst = dst.visit(lambda expr:_expr_loc_to_symb(expr, loc_db)) - line = "%s = %s" % (new_dst, new_src) - out.append(line) - out.append("") - return "\n".join(out) - -class IRBlock(object): - """Intermediate representation block object. - - Stand for an intermediate representation basic block. - """ - - __slots__ = ["_loc_db", "_loc_key", "_assignblks", "_dst", "_dst_linenb"] - - def __init__(self, loc_db, loc_key, assignblks): - """ - @loc_key: LocKey of the IR basic block - @assignblks: list of AssignBlock - """ - - assert isinstance(loc_key, m2_expr.LocKey) - self._loc_key = loc_key - self._loc_db = loc_db - for assignblk in assignblks: - assert isinstance(assignblk, AssignBlock) - self._assignblks = tuple(assignblks) - self._dst = None - self._dst_linenb = None - - def __eq__(self, other): - if self.__class__ is not other.__class__: - return False - if self.loc_key != other.loc_key: - return False - if self.loc_db != other.loc_db: - return False - if len(self.assignblks) != len(other.assignblks): - return False - for assignblk1, assignblk2 in zip(self.assignblks, other.assignblks): - if assignblk1 != assignblk2: - return False - return True - - def __ne__(self, other): - return not self == other - - def get_label(self): - warnings.warn('DEPRECATION WARNING: use ".loc_key" instead of ".label"') - return self.loc_key - - loc_key = property(lambda self:self._loc_key) - loc_db = property(lambda self:self._loc_db) - label = property(get_label) - - @property - def assignblks(self): - return self._assignblks - - @property - def irs(self): - warnings.warn('DEPRECATION WARNING: use "irblock.assignblks" instead of "irblock.irs"') - return self._assignblks - - def __iter__(self): - """Iterate on assignblks""" - return self._assignblks.__iter__() - - def __getitem__(self, index): - """Getitem on assignblks""" - return self._assignblks.__getitem__(index) - - def __len__(self): - """Length of assignblks""" - return self._assignblks.__len__() - - def is_dst_set(self): - return self._dst is not None - - def cache_dst(self): - final_dst = None - final_linenb = None - for linenb, assignblk in enumerate(self): - for dst, src in viewitems(assignblk): - if dst.is_id("IRDst"): - if final_dst is not None: - raise ValueError('Multiple destinations!') - final_dst = src - final_linenb = linenb - self._dst = final_dst - self._dst_linenb = final_linenb - return final_dst - - @property - def dst(self): - """Return the value of IRDst for the IRBlock""" - if self.is_dst_set(): - return self._dst - return self.cache_dst() - - def set_dst(self, value): - """Generate a new IRBlock with a dst (IRBlock) fixed to @value""" - irs = [] - dst_found = False - for assignblk in self: - new_assignblk = {} - for dst, src in viewitems(assignblk): - if dst.is_id("IRDst"): - assert dst_found is False - dst_found = True - new_assignblk[dst] = value - else: - new_assignblk[dst] = src - irs.append(AssignBlock(new_assignblk, assignblk.instr)) - return IRBlock(self.loc_db, self.loc_key, irs) - - @property - def dst_linenb(self): - """Line number of the IRDst setting statement in the current irs""" - if not self.is_dst_set(): - self.cache_dst() - return self._dst_linenb - - def to_string(self): - out = [] - names = self.loc_db.get_location_names(self.loc_key) - if not names: - node_name = "%s:" % self.loc_db.pretty_str(self.loc_key) - else: - node_name = "".join("%s:\n" % name for name in names) - out.append(node_name) - - for assignblk in self: - out.append(assignblk.to_string(self.loc_db)) - return '\n'.join(out) - - def __str__(self): - return self.to_string() - - def modify_exprs(self, mod_dst=None, mod_src=None): - """ - Generate a new IRBlock with its AssignBlock expressions modified - according to @mod_dst and @mod_src - @mod_dst: function called to modify Expression destination - @mod_src: function called to modify Expression source - """ - - if mod_dst is None: - mod_dst = lambda expr:expr - if mod_src is None: - mod_src = lambda expr:expr - - assignblks = [] - for assignblk in self: - new_assignblk = {} - for dst, src in viewitems(assignblk): - new_assignblk[mod_dst(dst)] = mod_src(src) - assignblks.append(AssignBlock(new_assignblk, assignblk.instr)) - return IRBlock(self.loc_db, self.loc_key, assignblks) - - def simplify(self, simplifier): - """ - Simplify expressions in each assignblock - @simplifier: ExpressionSimplifier instance - """ - modified = False - assignblks = [] - for assignblk in self: - new_assignblk = assignblk.simplify(simplifier) - if assignblk != new_assignblk: - modified = True - assignblks.append(new_assignblk) - return modified, IRBlock(self.loc_db, self.loc_key, assignblks) - - -class irbloc(IRBlock): - """ - DEPRECATED object - Use IRBlock instead of irbloc - """ - - def __init__(self, loc_key, irs, lines=None): - warnings.warn('DEPRECATION WARNING: use "IRBlock" instead of "irblock"') - super(irbloc, self).__init__(loc_key, irs) - - - -class IRCFG(DiGraph): - - """DiGraph for IR instances""" - - def __init__(self, irdst, loc_db, blocks=None, *args, **kwargs): - """Instantiate a IRCFG - @loc_db: LocationDB instance - @blocks: IR blocks - """ - self.loc_db = loc_db - if blocks is None: - blocks = {} - self._blocks = blocks - self._irdst = irdst - super(IRCFG, self).__init__(*args, **kwargs) - - @property - def IRDst(self): - return self._irdst - - @property - def blocks(self): - return self._blocks - - def add_irblock(self, irblock): - """ - Add the @irblock to the current IRCFG - @irblock: IRBlock instance - """ - self.blocks[irblock.loc_key] = irblock - self.add_node(irblock.loc_key) - - for dst in self.dst_trackback(irblock): - if dst.is_int(): - dst_loc_key = self.loc_db.get_or_create_offset_location(int(dst)) - dst = m2_expr.ExprLoc(dst_loc_key, irblock.dst.size) - if dst.is_loc(): - self.add_uniq_edge(irblock.loc_key, dst.loc_key) - - def escape_text(self, text): - return text - - def node2lines(self, node): - node_name = self.loc_db.pretty_str(node) - yield self.DotCellDescription( - text="%s" % node_name, - attr={ - 'align': 'center', - 'colspan': 2, - 'bgcolor': 'grey', - } - ) - if node not in self._blocks: - yield [self.DotCellDescription(text="NOT PRESENT", attr={'bgcolor': 'red'})] - return - for i, assignblk in enumerate(self._blocks[node]): - for dst, src in viewitems(assignblk): - line = "%s = %s" % ( - color_expr_html(dst, self.loc_db), - color_expr_html(src, self.loc_db) - ) - if self._dot_offset: - yield [self.DotCellDescription(text="%-4d" % i, attr={}), - self.DotCellDescription(text=line, attr={})] - else: - yield self.DotCellDescription(text=line, attr={}) - yield self.DotCellDescription(text="", attr={}) - - def edge_attr(self, src, dst): - if src not in self._blocks or dst not in self._blocks: - return {} - src_irdst = self._blocks[src].dst - edge_color = "blue" - if isinstance(src_irdst, m2_expr.ExprCond): - src1, src2 = src_irdst.src1, src_irdst.src2 - if src1.is_loc(dst): - edge_color = "limegreen" - elif src2.is_loc(dst): - edge_color = "red" - return {"color": edge_color} - - def node_attr(self, node): - if node not in self._blocks: - return {'style': 'filled', 'fillcolor': 'red'} - return {} - - def dot(self, offset=False): - """ - @offset: (optional) if set, add the corresponding line number in each - node - """ - self._dot_offset = offset - return super(IRCFG, self).dot() - - def get_loc_key(self, addr): - """Transforms an ExprId/ExprInt/loc_key/int into a loc_key - @addr: an ExprId/ExprInt/loc_key/int""" - - if isinstance(addr, m2_expr.LocKey): - return addr - elif isinstance(addr, m2_expr.ExprLoc): - return addr.loc_key - - try: - addr = int(addr) - except (ValueError, TypeError): - return None - - return self.loc_db.get_offset_location(addr) - - - def get_or_create_loc_key(self, addr): - """Transforms an ExprId/ExprInt/loc_key/int into a loc_key - If the offset @addr is not in the LocationDB, create it - @addr: an ExprId/ExprInt/loc_key/int""" - - loc_key = self.get_loc_key(addr) - if loc_key is not None: - return loc_key - - return self.loc_db.add_location(offset=int(addr)) - - def get_block(self, addr): - """Returns the irbloc associated to an ExprId/ExprInt/loc_key/int - @addr: an ExprId/ExprInt/loc_key/int""" - - loc_key = self.get_loc_key(addr) - if loc_key is None: - return None - return self.blocks.get(loc_key, None) - - def getby_offset(self, offset): - """ - Return the set of loc_keys of irblocks containing @offset - @offset: address - """ - out = set() - for irb in viewvalues(self.blocks): - for assignblk in irb: - instr = assignblk.instr - if instr is None: - continue - if instr.offset <= offset < instr.offset + instr.l: - out.add(irb.loc_key) - return out - - - def simplify(self, simplifier): - """ - Simplify expressions in each irblocks - @simplifier: ExpressionSimplifier instance - """ - modified = False - for loc_key, block in list(viewitems(self.blocks)): - assignblks = [] - for assignblk in block: - new_assignblk = assignblk.simplify(simplifier) - if assignblk != new_assignblk: - modified = True - assignblks.append(new_assignblk) - self.blocks[loc_key] = IRBlock(self.loc_db, loc_key, assignblks) - return modified - - def _extract_dst(self, todo, done): - """ - Naive extraction of @todo destinations - WARNING: @todo and @done are modified - """ - out = set() - while todo: - dst = todo.pop() - if dst.is_loc(): - done.add(dst) - elif dst.is_mem() or dst.is_int(): - done.add(dst) - elif dst.is_cond(): - todo.add(dst.src1) - todo.add(dst.src2) - elif dst.is_id(): - out.add(dst) - else: - done.add(dst) - return out - - def dst_trackback(self, irb): - """ - Naive backtracking of IRDst - @irb: irbloc instance - """ - todo = set([irb.dst]) - done = set() - - for assignblk in reversed(irb): - if not todo: - break - out = self._extract_dst(todo, done) - found = set() - follow = set() - for dst in out: - if dst in assignblk: - follow.add(assignblk[dst]) - found.add(dst) - - follow.update(out.difference(found)) - todo = follow - - return done - - -class DiGraphIR(IRCFG): - """ - DEPRECATED object - Use IRCFG instead of DiGraphIR - """ - - def __init__(self, *args, **kwargs): - warnings.warn('DEPRECATION WARNING: use "IRCFG" instead of "DiGraphIR"') - raise NotImplementedError("Deprecated") - - -class Lifter(object): - """ - Intermediate representation object - - Allow native assembly to intermediate representation traduction - """ - - def __init__(self, arch, attrib, loc_db): - self.pc = arch.getpc(attrib) - self.sp = arch.getsp(attrib) - self.arch = arch - self.attrib = attrib - self.loc_db = loc_db - self.IRDst = None - - def get_ir(self, instr): - raise NotImplementedError("Abstract Method") - - def new_ircfg(self, *args, **kwargs): - """ - Return a new instance of IRCFG - """ - return IRCFG(self.IRDst, self.loc_db, *args, **kwargs) - - def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): - """ - Return a new instance of IRCFG from an @asmcfg - @asmcfg: AsmCFG instance - """ - - ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) - for block in asmcfg.blocks: - self.add_asmblock_to_ircfg(block, ircfg) - return ircfg - - def instr2ir(self, instr): - ir_bloc_cur, extra_irblocks = self.get_ir(instr) - for index, irb in enumerate(extra_irblocks): - irs = [] - for assignblk in irb: - irs.append(AssignBlock(assignblk, instr)) - extra_irblocks[index] = IRBlock(self.loc_db, irb.loc_key, irs) - assignblk = AssignBlock(ir_bloc_cur, instr) - return assignblk, extra_irblocks - - def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): - """ - Add the native instruction @instr to the @ircfg - @instr: instruction instance - @ircfg: IRCFG instance - @loc_key: loc_key instance of the instruction destination - @gen_pc_updt: insert PC update effects between instructions - """ - - if loc_key is None: - offset = getattr(instr, "offset", None) - loc_key = self.loc_db.get_or_create_offset_location(offset) - block = AsmBlock(self.loc_db, loc_key) - block.lines = [instr] - self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) - return loc_key - - def gen_pc_update(self, assignments, instr): - offset = m2_expr.ExprInt(instr.offset, self.pc.size) - assignments.append(AssignBlock({self.pc:offset}, instr)) - - def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): - """ - Add the IR effects of an instruction to the current state. - - Returns a bool: - * True if the current assignments list must be split - * False in other cases. - - @instr: native instruction - @block: native block source - @assignments: list of current AssignBlocks - @ir_blocks_all: list of additional effects - @gen_pc_updt: insert PC update effects between instructions - """ - if gen_pc_updt is not False: - self.gen_pc_update(assignments, instr) - - assignblk, ir_blocks_extra = self.instr2ir(instr) - assignments.append(assignblk) - ir_blocks_all += ir_blocks_extra - if ir_blocks_extra: - return True - return False - - def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): - """ - Add a native block to the current IR - @block: native assembly block - @ircfg: IRCFG instance - @gen_pc_updt: insert PC update effects between instructions - """ - - loc_key = block.loc_key - ir_blocks_all = [] - - if isinstance(block, AsmBlockBad): - return ir_blocks_all - - assignments = [] - for instr in block.lines: - if loc_key is None: - assignments = [] - loc_key = self.get_loc_key_for_instr(instr) - split = self.add_instr_to_current_state( - instr, block, assignments, - ir_blocks_all, gen_pc_updt - ) - if split: - ir_blocks_all.append(IRBlock(self.loc_db, loc_key, assignments)) - loc_key = None - assignments = [] - if loc_key is not None: - ir_blocks_all.append(IRBlock(self.loc_db, loc_key, assignments)) - - new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) - for irblock in new_ir_blocks_all: - ircfg.add_irblock(irblock) - return new_ir_blocks_all - - def add_block(self, block, gen_pc_updt=False): - """ - DEPRECATED function - Use add_asmblock_to_ircfg instead of add_block - """ - warnings.warn("""DEPRECATION WARNING - ircfg is now out of Lifter - Use: - ircfg = lifter.new_ircfg() - lifter.add_asmblock_to_ircfg(block, ircfg) - """) - raise RuntimeError("API Deprecated") - - def add_bloc(self, block, gen_pc_updt=False): - """ - DEPRECATED function - Use add_asmblock_to_ircfg instead of add_bloc - """ - self.add_block(block, gen_pc_updt) - - def get_next_loc_key(self, instr): - loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) - return loc_key - - def get_loc_key_for_instr(self, instr): - """Returns the loc_key associated to an instruction - @instr: current instruction""" - return self.loc_db.get_or_create_offset_location(instr.offset) - - def gen_loc_key_and_expr(self, size): - """ - Return a loc_key and it's corresponding ExprLoc - @size: size of expression - """ - loc_key = self.loc_db.add_location() - return loc_key, m2_expr.ExprLoc(loc_key, size) - - def expr_fix_regs_for_mode(self, expr, *args, **kwargs): - return expr - - def expraff_fix_regs_for_mode(self, expr, *args, **kwargs): - return expr - - def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs): - return irblock - - def is_pc_written(self, block): - """Return the first Assignblk of the @block in which PC is written - @block: IRBlock instance""" - all_pc = viewvalues(self.arch.pc) - for assignblk in block: - if assignblk.dst in all_pc: - return assignblk - return None - - def set_empty_dst_to_next(self, block, ir_blocks): - for index, irblock in enumerate(ir_blocks): - if irblock.dst is not None: - continue - next_loc_key = block.get_next() - if next_loc_key is None: - loc_key = None - if block.lines: - line = block.lines[-1] - if line.offset is not None: - loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) - if loc_key is None: - loc_key = self.loc_db.add_location() - block.add_cst(loc_key, AsmConstraint.c_next) - else: - loc_key = next_loc_key - dst = m2_expr.ExprLoc(loc_key, self.pc.size) - if irblock.assignblks: - instr = irblock.assignblks[-1].instr - else: - instr = None - assignblk = AssignBlock({self.IRDst: dst}, instr) - ir_blocks[index] = IRBlock(self.loc_db, irblock.loc_key, list(irblock.assignblks) + [assignblk]) - - def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): - self.set_empty_dst_to_next(block, ir_blocks) - - new_irblocks = [] - for irblock in ir_blocks: - new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) - ircfg.add_irblock(new_irblock) - new_irblocks.append(new_irblock) - return new_irblocks - - -class IntermediateRepresentation(Lifter): - """ - DEPRECATED object - Use Lifter instead of IntermediateRepresentation - """ - - def __init__(self, arch, attrib, loc_db): - warnings.warn('DEPRECATION WARNING: use "Lifter" instead of "IntermediateRepresentation"') - super(IntermediateRepresentation, self).__init__(arch, attrib, loc_db) - - -class ir(Lifter): - """ - DEPRECATED object - Use Lifter instead of ir - """ - - def __init__(self, loc_key, irs, lines=None): - warnings.warn('DEPRECATION WARNING: use "Lifter" instead of "ir"') - super(ir, self).__init__(loc_key, irs, lines) |