<s> import networkx <EOL> import pyvex <EOL> import simuvex <EOL> class Blade ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , graph , dst_run , dst_stmt_idx , direction = '<STR_LIT>' , project = None , cfg = None , ignore_sp = False , <EOL> ignore_bp = False , max_level = <NUM_LIT:3> ) : <EOL> """<STR_LIT>""" <EOL> self . _graph = graph <EOL> self . _dst_run = dst_run <EOL> self . _dst_stmt_idx = dst_stmt_idx <EOL> self . _ignore_sp = ignore_sp <EOL> self . _ignore_bp = ignore_bp <EOL> self . _max_level = max_level <EOL> self . _slice = networkx . DiGraph ( ) <EOL> self . project = project <EOL> self . _cfg = cfg <EOL> if self . _cfg is None : <EOL> raise AngrBladeError ( '<STR_LIT>' ) <EOL> if not self . _in_graph ( self . _dst_run ) : <EOL> raise AngrBladeError ( "<STR_LIT>" ) <EOL> self . _run_cache = { } <EOL> self . _traced_runs = set ( ) <EOL> if direction == '<STR_LIT>' : <EOL> self . _backward_slice ( ) <EOL> elif direction == '<STR_LIT>' : <EOL> raise AngrBladeError ( '<STR_LIT>' ) <EOL> else : <EOL> raise AngrBladeError ( "<STR_LIT>" , direction ) <EOL> @ property <EOL> def slice ( self ) : <EOL> return self . _slice <EOL> def _get_irsb ( self , v ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( v , simuvex . SimProcedure ) : <EOL> raise AngrBladeSimProcError ( ) <EOL> elif isinstance ( v , simuvex . SimIRSB ) : <EOL> v = v . addr <EOL> elif isinstance ( v , CFGNode ) : <EOL> v = v . addr <EOL> if type ( v ) in ( int , long ) : <EOL> if v in self . _run_cache : <EOL> return self . _run_cache [ v ] <EOL> if self . project : <EOL> irsb = self . project . factory . block ( v ) . vex <EOL> self . _run_cache [ v ] = irsb <EOL> return irsb <EOL> else : <EOL> raise AngrBladeError ( "<STR_LIT>" ) <EOL> else : <EOL> raise AngrBladeError ( '<STR_LIT>' , type ( v ) ) <EOL> def _get_cfgnode ( self , thing ) : <EOL> """<STR_LIT>""" <EOL> return self . _cfg . get_any_node ( self . _get_addr ( thing ) ) <EOL> def _get_addr ( self , v ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( v , simuvex . SimIRSB ) or isinstance ( v , simuvex . SimProcedure ) : <EOL> if type ( self . _graph . nodes ( ) [ <NUM_LIT:0> ] ) in ( int , long ) : <EOL> return v . addr <EOL> else : <EOL> return v <EOL> elif isinstance ( v , CFGNode ) : <EOL> return v . addr <EOL> elif type ( v ) in ( int , long ) : <EOL> return v <EOL> else : <EOL> raise AngrBladeError ( '<STR_LIT>' , type ( v ) ) <EOL> def _in_graph ( self , v ) : <EOL> return self . _get_cfgnode ( v ) in self . _graph <EOL> def _inslice_callback ( self , stmt_idx , stmt , infodict ) : <EOL> tpl = ( infodict [ '<STR_LIT>' ] , stmt_idx ) <EOL> if '<STR_LIT>' in infodict and infodict [ '<STR_LIT>' ] : <EOL> prev = infodict [ '<STR_LIT>' ] <EOL> self . _slice . add_edge ( tpl , prev ) <EOL> else : <EOL> self . _slice . add_node ( tpl ) <EOL> infodict [ '<STR_LIT>' ] = tpl <EOL> def _backward_slice ( self ) : <EOL> """<STR_LIT>""" <EOL> temps = set ( ) <EOL> regs = set ( ) <EOL> stmts = self . _get_irsb ( self . _dst_run ) . statements <EOL> if self . _dst_stmt_idx != - <NUM_LIT:1> : <EOL> dst_stmt = stmts [ self . _dst_stmt_idx ] <EOL> if type ( dst_stmt ) is pyvex . IRStmt . Put : <EOL> regs . add ( dst_stmt . offset ) <EOL> elif type ( dst_stmt ) is pyvex . IRStmt . WrTmp : <EOL> temps . add ( dst_stmt . tmp ) <EOL> else : <EOL> raise AngrBladeError ( '<STR_LIT>' ) <EOL> prev = ( self . _get_addr ( self . _dst_run ) , self . _dst_stmt_idx ) <EOL> else : <EOL> next_expr = self . _get_irsb ( self . _dst_run ) . next <EOL> if type ( next_expr ) is pyvex . IRExpr . RdTmp : <EOL> temps . add ( next_expr . tmp ) <EOL> elif type ( next_expr ) is pyvex . IRExpr . Const : <EOL> pass <EOL> else : <EOL> raise AngrBladeError ( '<STR_LIT>' % type ( next_expr ) ) <EOL> self . _dst_stmt_idx = len ( stmts ) - <NUM_LIT:1> <EOL> prev = ( self . _get_addr ( self . _dst_run ) , '<STR_LIT:default>' ) <EOL> slicer = simuvex . SimSlicer ( self . project . arch , stmts , <EOL> target_tmps = temps , <EOL> target_regs = regs , <EOL> target_stack_offsets = None , <EOL> inslice_callback = self . _inslice_callback , <EOL> inslice_callback_infodict = { <EOL> '<STR_LIT>' : self . _get_irsb ( self . _dst_run ) . _addr , <EOL> '<STR_LIT>' : prev , <EOL> } ) <EOL> regs = slicer . final_regs <EOL> if self . _ignore_sp and self . project . arch . sp_offset in regs : <EOL> regs . remove ( self . project . arch . sp_offset ) <EOL> if self . _ignore_bp and self . project . arch . bp_offset in regs : <EOL> regs . remove ( self . project . arch . bp_offset ) <EOL> stack_offsets = slicer . final_stack_offsets <EOL> prev = slicer . inslice_callback_infodict [ '<STR_LIT>' ] <EOL> if regs or stack_offsets : <EOL> cfgnode = self . _get_cfgnode ( self . _dst_run ) <EOL> in_edges = self . _graph . in_edges ( cfgnode , data = True ) <EOL> for pred , _ , data in in_edges : <EOL> if pred not in self . _traced_runs : <EOL> self . _traced_runs . add ( pred ) <EOL> self . _backward_slice_recursive ( self . _max_level - <NUM_LIT:1> , pred , regs , stack_offsets , prev , data [ '<STR_LIT>' ] ) <EOL> def _backward_slice_recursive ( self , level , run , regs , stack_offsets , prev , exit_stmt_idx ) : <EOL> if level <= <NUM_LIT:0> : <EOL> return <EOL> temps = set ( ) <EOL> regs = regs . copy ( ) <EOL> stmts = self . _get_irsb ( run ) . statements <EOL> if exit_stmt_idx is None or exit_stmt_idx == '<STR_LIT:default>' : <EOL> next_expr = self . _get_irsb ( run ) . next <EOL> if type ( next_expr ) is pyvex . IRExpr . RdTmp : <EOL> temps . add ( next_expr . tmp ) <EOL> else : <EOL> exit_stmt = self . _get_irsb ( run ) . statements [ exit_stmt_idx ] <EOL> if type ( exit_stmt . guard ) is pyvex . IRExpr . RdTmp : <EOL> temps . add ( exit_stmt . guard . tmp ) <EOL> irsb_addr = self . _get_addr ( run ) <EOL> self . _inslice_callback ( exit_stmt_idx , exit_stmt , { '<STR_LIT>' : irsb_addr , '<STR_LIT>' : prev } ) <EOL> prev = ( irsb_addr , exit_stmt_idx ) <EOL> slicer = simuvex . SimSlicer ( self . project . arch , stmts , <EOL> target_tmps = temps , <EOL> target_regs = regs , <EOL> target_stack_offsets = stack_offsets , <EOL> inslice_callback = self . _inslice_callback , <EOL> inslice_callback_infodict = { <EOL> '<STR_LIT>' : self . _get_addr ( run ) , <EOL> '<STR_LIT>' : prev <EOL> } ) <EOL> regs = slicer . final_regs <EOL> if self . _ignore_sp and self . project . arch . sp_offset in regs : <EOL> regs . remove ( self . project . arch . sp_offset ) <EOL> if self . _ignore_bp and self . project . arch . bp_offset in regs : <EOL> regs . remove ( self . project . arch . bp_offset ) <EOL> stack_offsets = slicer . final_stack_offsets <EOL> prev = slicer . inslice_callback_infodict [ '<STR_LIT>' ] <EOL> if regs or stack_offsets : <EOL> in_edges = self . _graph . in_edges ( self . _get_cfgnode ( run ) , data = True ) <EOL> for pred , _ , data in in_edges : <EOL> if pred not in self . _traced_runs : <EOL> self . _traced_runs . add ( pred ) <EOL> self . _backward_slice_recursive ( level - <NUM_LIT:1> , pred , regs , stack_offsets , prev , data [ '<STR_LIT>' ] ) <EOL> from . errors import AngrBladeError , AngrBladeSimProcError <EOL> from . analyses . cfg_node import CFGNode </s>
