miasm2.expression.expression_reduce module
Expression reducer: Apply reduction rules to an Expression ast
""" Expression reducer: Apply reduction rules to an Expression ast """ import logging from miasm2.expression.expression import ExprInt, ExprId, ExprLoc, ExprOp, \ ExprSlice, ExprCompose, ExprMem, ExprCond log_reduce = logging.getLogger("expr_reduce") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log_reduce.addHandler(console_handler) log_reduce.setLevel(logging.WARNING) class ExprNode(object): """Clone of Expression object with additionnal information""" def __init__(self, expr): self.expr = expr # Generic field to store custom node information self.info = None self.arg, self.args = None, None self.cond, self.src1, self.src2 = None, None, None def __repr__(self): expr = self.expr if self.info is not None: out = repr(self.info) elif expr.is_int() or expr.is_id() or expr.is_loc(): out = str(expr) elif expr.is_mem(): out = "@%d[%r]" % (self.expr.size, self.arg) elif expr.is_slice(): out = "%r[%d:%d]" % (self.arg, expr.start, expr.stop) elif expr.is_op(): if len(self.args) == 1: out = "(%s(%r))" % (expr.op, self.args[0]) else: out = "(%s)" % expr.op.join(repr(arg) for arg in self.args) elif expr.is_compose(): out = "{%s}" % ', '.join(repr(arg) for arg in self.args) elif expr.is_cond(): out = "(%r?%r:%r)" % (self.cond, self.src1, self.src2) else: raise TypeError("Unknown node Type %r", type(expr)) return out class ExprReducer(object): """Apply reduction rules to an expr reduction_rules: list of ordered reduction rules List of function representing reduction rules Function API: reduction_xxx(self, node, lvl=0) with: * node: the ExprNode to qualify * lvl: [optional] the recursion level Returns: * None if the reduction rule is not applied * the resulting information to store in the ExprNode.info allow_none_result: allow missing reduction rules """ reduction_rules = [] allow_none_result = False def expr2node(self, expr): """Build ExprNode mirror of @expr @expr: Expression to analyze """ if isinstance(expr, (ExprId, ExprLoc, ExprInt)): node = ExprNode(expr) elif isinstance(expr, (ExprMem, ExprSlice)): son = self.expr2node(expr.arg) node = ExprNode(expr) node.arg = son elif isinstance(expr, ExprOp): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCompose): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCond): node = ExprNode(expr) node.cond = self.expr2node(expr.cond) node.src1 = self.expr2node(expr.src1) node.src2 = self.expr2node(expr.src2) else: raise TypeError("Unknown Expr Type %r", type(expr)) return node def reduce(self, expr, **kwargs): """Returns an ExprNode tree mirroring @expr tree. The ExprNode is computed by applying reduction rules to the expression @expr @expr: an Expression """ node = self.expr2node(expr) return self.categorize(node, lvl=0, **kwargs) def categorize(self, node, lvl=0, **kwargs): """Recursively apply rules to @node @node: ExprNode to analyze @lvl: actual recusion level """ expr = node.expr log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr) if isinstance(expr, (ExprId, ExprInt, ExprLoc)): pass elif isinstance(expr, ExprMem): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprMem(arg.expr, expr.size)) node.arg = arg elif isinstance(expr, ExprSlice): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprSlice(arg.expr, expr.start, expr.stop)) node.arg = arg elif isinstance(expr, ExprOp): new_args = [] for arg in node.args: new_a = self.categorize(arg, lvl=lvl + 1, **kwargs) assert new_a.expr.size == arg.expr.size new_args.append(new_a) node = ExprNode(ExprOp(expr.op, *[x.expr for x in new_args])) node.args = new_args expr = node.expr elif isinstance(expr, ExprCompose): new_args = [] new_expr_args = [] for arg in node.args: arg = self.categorize(arg, lvl=lvl + 1, **kwargs) new_args.append(arg) new_expr_args.append(arg.expr) new_expr = ExprCompose(*new_expr_args) node = ExprNode(new_expr) node.args = new_args elif isinstance(expr, ExprCond): cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs) src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs) src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs) node = ExprNode(ExprCond(cond.expr, src1.expr, src2.expr)) node.cond, node.src1, node.src2 = cond, src1, src2 else: raise TypeError("Unknown Expr Type %r", type(expr)) node.info = self.apply_rules(node, lvl=lvl, **kwargs) log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr, node.info) return node def apply_rules(self, node, lvl=0, **kwargs): """Find and apply reduction rules to @node @node: ExprNode to analyse @lvl: actuel recusion level """ for rule in self.reduction_rules: ret = rule(self, node, lvl=lvl, **kwargs) if ret is not None: log_reduce.debug("\t" * lvl + "Rule found: %r", rule) return ret if not self.allow_none_result: raise RuntimeError('Missing reduction rule for %r' % node.expr)
Module variables
var console_handler
var log_reduce
Classes
class ExprNode
Clone of Expression object with additionnal information
class ExprNode(object): """Clone of Expression object with additionnal information""" def __init__(self, expr): self.expr = expr # Generic field to store custom node information self.info = None self.arg, self.args = None, None self.cond, self.src1, self.src2 = None, None, None def __repr__(self): expr = self.expr if self.info is not None: out = repr(self.info) elif expr.is_int() or expr.is_id() or expr.is_loc(): out = str(expr) elif expr.is_mem(): out = "@%d[%r]" % (self.expr.size, self.arg) elif expr.is_slice(): out = "%r[%d:%d]" % (self.arg, expr.start, expr.stop) elif expr.is_op(): if len(self.args) == 1: out = "(%s(%r))" % (expr.op, self.args[0]) else: out = "(%s)" % expr.op.join(repr(arg) for arg in self.args) elif expr.is_compose(): out = "{%s}" % ', '.join(repr(arg) for arg in self.args) elif expr.is_cond(): out = "(%r?%r:%r)" % (self.cond, self.src1, self.src2) else: raise TypeError("Unknown node Type %r", type(expr)) return out
Ancestors (in MRO)
- ExprNode
- __builtin__.object
Instance variables
var expr
var info
Methods
def __init__(
self, expr)
def __init__(self, expr): self.expr = expr # Generic field to store custom node information self.info = None self.arg, self.args = None, None self.cond, self.src1, self.src2 = None, None, None
class ExprReducer
Apply reduction rules to an expr
reduction_rules: list of ordered reduction rules
List of function representing reduction rules Function API: reduction_xxx(self, node, lvl=0) with: node: the ExprNode to qualify lvl: [optional] the recursion level Returns: None if the reduction rule is not applied the resulting information to store in the ExprNode.info
allow_none_result: allow missing reduction rules
class ExprReducer(object): """Apply reduction rules to an expr reduction_rules: list of ordered reduction rules List of function representing reduction rules Function API: reduction_xxx(self, node, lvl=0) with: * node: the ExprNode to qualify * lvl: [optional] the recursion level Returns: * None if the reduction rule is not applied * the resulting information to store in the ExprNode.info allow_none_result: allow missing reduction rules """ reduction_rules = [] allow_none_result = False def expr2node(self, expr): """Build ExprNode mirror of @expr @expr: Expression to analyze """ if isinstance(expr, (ExprId, ExprLoc, ExprInt)): node = ExprNode(expr) elif isinstance(expr, (ExprMem, ExprSlice)): son = self.expr2node(expr.arg) node = ExprNode(expr) node.arg = son elif isinstance(expr, ExprOp): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCompose): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCond): node = ExprNode(expr) node.cond = self.expr2node(expr.cond) node.src1 = self.expr2node(expr.src1) node.src2 = self.expr2node(expr.src2) else: raise TypeError("Unknown Expr Type %r", type(expr)) return node def reduce(self, expr, **kwargs): """Returns an ExprNode tree mirroring @expr tree. The ExprNode is computed by applying reduction rules to the expression @expr @expr: an Expression """ node = self.expr2node(expr) return self.categorize(node, lvl=0, **kwargs) def categorize(self, node, lvl=0, **kwargs): """Recursively apply rules to @node @node: ExprNode to analyze @lvl: actual recusion level """ expr = node.expr log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr) if isinstance(expr, (ExprId, ExprInt, ExprLoc)): pass elif isinstance(expr, ExprMem): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprMem(arg.expr, expr.size)) node.arg = arg elif isinstance(expr, ExprSlice): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprSlice(arg.expr, expr.start, expr.stop)) node.arg = arg elif isinstance(expr, ExprOp): new_args = [] for arg in node.args: new_a = self.categorize(arg, lvl=lvl + 1, **kwargs) assert new_a.expr.size == arg.expr.size new_args.append(new_a) node = ExprNode(ExprOp(expr.op, *[x.expr for x in new_args])) node.args = new_args expr = node.expr elif isinstance(expr, ExprCompose): new_args = [] new_expr_args = [] for arg in node.args: arg = self.categorize(arg, lvl=lvl + 1, **kwargs) new_args.append(arg) new_expr_args.append(arg.expr) new_expr = ExprCompose(*new_expr_args) node = ExprNode(new_expr) node.args = new_args elif isinstance(expr, ExprCond): cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs) src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs) src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs) node = ExprNode(ExprCond(cond.expr, src1.expr, src2.expr)) node.cond, node.src1, node.src2 = cond, src1, src2 else: raise TypeError("Unknown Expr Type %r", type(expr)) node.info = self.apply_rules(node, lvl=lvl, **kwargs) log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr, node.info) return node def apply_rules(self, node, lvl=0, **kwargs): """Find and apply reduction rules to @node @node: ExprNode to analyse @lvl: actuel recusion level """ for rule in self.reduction_rules: ret = rule(self, node, lvl=lvl, **kwargs) if ret is not None: log_reduce.debug("\t" * lvl + "Rule found: %r", rule) return ret if not self.allow_none_result: raise RuntimeError('Missing reduction rule for %r' % node.expr)
Ancestors (in MRO)
- ExprReducer
- __builtin__.object
Class variables
var allow_none_result
var reduction_rules
Methods
def apply_rules(
self, node, lvl=0, **kwargs)
Find and apply reduction rules to @node
@node: ExprNode to analyse @lvl: actuel recusion level
def apply_rules(self, node, lvl=0, **kwargs): """Find and apply reduction rules to @node @node: ExprNode to analyse @lvl: actuel recusion level """ for rule in self.reduction_rules: ret = rule(self, node, lvl=lvl, **kwargs) if ret is not None: log_reduce.debug("\t" * lvl + "Rule found: %r", rule) return ret if not self.allow_none_result: raise RuntimeError('Missing reduction rule for %r' % node.expr)
def categorize(
self, node, lvl=0, **kwargs)
Recursively apply rules to @node
@node: ExprNode to analyze @lvl: actual recusion level
def categorize(self, node, lvl=0, **kwargs): """Recursively apply rules to @node @node: ExprNode to analyze @lvl: actual recusion level """ expr = node.expr log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr) if isinstance(expr, (ExprId, ExprInt, ExprLoc)): pass elif isinstance(expr, ExprMem): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprMem(arg.expr, expr.size)) node.arg = arg elif isinstance(expr, ExprSlice): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNode(ExprSlice(arg.expr, expr.start, expr.stop)) node.arg = arg elif isinstance(expr, ExprOp): new_args = [] for arg in node.args: new_a = self.categorize(arg, lvl=lvl + 1, **kwargs) assert new_a.expr.size == arg.expr.size new_args.append(new_a) node = ExprNode(ExprOp(expr.op, *[x.expr for x in new_args])) node.args = new_args expr = node.expr elif isinstance(expr, ExprCompose): new_args = [] new_expr_args = [] for arg in node.args: arg = self.categorize(arg, lvl=lvl + 1, **kwargs) new_args.append(arg) new_expr_args.append(arg.expr) new_expr = ExprCompose(*new_expr_args) node = ExprNode(new_expr) node.args = new_args elif isinstance(expr, ExprCond): cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs) src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs) src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs) node = ExprNode(ExprCond(cond.expr, src1.expr, src2.expr)) node.cond, node.src1, node.src2 = cond, src1, src2 else: raise TypeError("Unknown Expr Type %r", type(expr)) node.info = self.apply_rules(node, lvl=lvl, **kwargs) log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr, node.info) return node
def expr2node(
self, expr)
Build ExprNode mirror of @expr
@expr: Expression to analyze
def expr2node(self, expr): """Build ExprNode mirror of @expr @expr: Expression to analyze """ if isinstance(expr, (ExprId, ExprLoc, ExprInt)): node = ExprNode(expr) elif isinstance(expr, (ExprMem, ExprSlice)): son = self.expr2node(expr.arg) node = ExprNode(expr) node.arg = son elif isinstance(expr, ExprOp): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCompose): sons = [self.expr2node(arg) for arg in expr.args] node = ExprNode(expr) node.args = sons elif isinstance(expr, ExprCond): node = ExprNode(expr) node.cond = self.expr2node(expr.cond) node.src1 = self.expr2node(expr.src1) node.src2 = self.expr2node(expr.src2) else: raise TypeError("Unknown Expr Type %r", type(expr)) return node
def reduce(
self, expr, **kwargs)
Returns an ExprNode tree mirroring @expr tree. The ExprNode is computed by applying reduction rules to the expression @expr
@expr: an Expression
def reduce(self, expr, **kwargs): """Returns an ExprNode tree mirroring @expr tree. The ExprNode is computed by applying reduction rules to the expression @expr @expr: an Expression """ node = self.expr2node(expr) return self.categorize(node, lvl=0, **kwargs)