def _backward_slice_recursive(self, run, regs, prev): temps = set() regs = regs.copy() stmts = self._get_run(run).irsb.statements # Initialize the temps set with whatever in the `next` attribute of this irsb next_expr = self._get_run(run).irsb.next if type(next_expr) is pyvex.IRExpr.RdTmp: temps.add(next_expr.tmp) slicer = simuvex.SimSlicer(stmts, temps, regs, inslice_callback=self._inslice_callback, inslice_callback_infodict={ 'irsb_addr': self._get_run(run).addr, 'prev': prev }) regs = slicer.final_regs prev = slicer.inslice_callback_infodict['prev'] if regs: predecessors = self._graph.predecessors(self._normalize(run)) for p in predecessors: if p not in self._traced_runs: self._traced_runs.add(p) self._backward_slice_recursive(p, regs, prev)
def _backward_slice_recursive(self, level, run, regs, stack_offsets, prev, exit_stmt_idx): if level <= 0: return temps = set() regs = regs.copy() stmts = self._get_irsb(run).statements if exit_stmt_idx is None or exit_stmt_idx == 'default': # Initialize the temps set with whatever in the `next` attribute of this irsb next_expr = self._get_irsb(run).next if type(next_expr) is pyvex.IRExpr.RdTmp: temps.add(next_expr.tmp) else: exit_stmt = self._get_irsb(run).statements[exit_stmt_idx] if type(exit_stmt.guard) is pyvex.IRExpr.RdTmp: temps.add(exit_stmt.guard.tmp) # Put it in our slice irsb_addr = self._get_addr(run) self._inslice_callback(exit_stmt_idx, exit_stmt, {'irsb_addr': irsb_addr, 'prev': prev}) prev = (irsb_addr, exit_stmt_idx) slicer = simuvex.SimSlicer(self.project.arch, stmts, target_tmps=temps, target_regs=regs, target_stack_offsets=stack_offsets, inslice_callback=self._inslice_callback, inslice_callback_infodict={ 'irsb_addr' : self._get_addr(run), 'prev' : prev }) regs = slicer.final_regs if self._ignore_sp and self.project.arch.sp_offset in regs: regs.remove(self.project.arch.sp_offset) if self._ignore_bp and self.project.arch.bp_offset in regs: regs.remove(self.project.arch.bp_offset) stack_offsets = slicer.final_stack_offsets prev = slicer.inslice_callback_infodict['prev'] if regs or stack_offsets: in_edges = self._graph.in_edges(self._get_cfgnode(run), data=True) for pred, _, data in in_edges: if pred not in self._traced_runs: self._traced_runs.add(pred) self._backward_slice_recursive(level - 1, pred, regs, stack_offsets, prev, data['stmt_idx'])
def _backward_slice(self): ''' Backward slicing. We support the following IRStmts: # WrTmp # Put We support the following IRExprs: # Get # RdTmp # Const :return: ''' temps = set() regs = set() # Retrieve the target: are we slicing from a register(IRStmt.Put), or a temp(IRStmt.WrTmp)? stmts = self._get_run(self._dst_run).irsb.statements if self._dst_stmt_idx != -1: dst_stmt = stmts[self._dst_stmt_idx] if type(dst_stmt) is pyvex.IRStmt.Put: regs.add(dst_stmt.offset) elif type(dst_stmt) is pyvex.IRStmt.WrTmp: temps.add(dst_stmt.tmp) else: raise AngrBladeError( 'Incorrect type of the specified target statement. We only support Put and WrTmp.' ) else: next_expr = self._get_run(self._dst_run).irsb.next if type(next_expr) is pyvex.IRExpr.RdTmp: temps.add(next_expr.tmp) elif type(next_expr) is pyvex.IRExpr.Const: # A const doesn't rely on anything else! pass else: raise AngrBladeError('Unsupported type for irsb.next: %s' % type(next_expr)) # Then we gotta start from the very last statement! self._dst_stmt_idx = len(stmts) - 1 slicer = simuvex.SimSlicer(stmts, temps, regs, inslice_callback=self._inslice_callback, inslice_callback_infodict={ 'irsb_addr': self._get_run(self._dst_run).addr }) regs = slicer.final_regs prev = slicer.inslice_callback_infodict['prev'] if regs: predecessors = self._graph.predecessors( self._normalize(self._dst_run)) for p in predecessors: if p not in self._traced_runs: self._traced_runs.add(p) self._backward_slice_recursive(p, regs, prev)
def _backward_slice(self): """ Backward slicing. We support the following IRStmts: # WrTmp # Put We support the following IRExprs: # Get # RdTmp # Const :return: """ temps = set() regs = set() # Retrieve the target: are we slicing from a register(IRStmt.Put), or a temp(IRStmt.WrTmp)? stmts = self._get_irsb(self._dst_run).statements if self._dst_stmt_idx != -1: dst_stmt = stmts[self._dst_stmt_idx] if type(dst_stmt) is pyvex.IRStmt.Put: regs.add(dst_stmt.offset) elif type(dst_stmt) is pyvex.IRStmt.WrTmp: temps.add(dst_stmt.tmp) else: raise AngrBladeError('Incorrect type of the specified target statement. We only support Put and WrTmp.') prev = (self._get_addr(self._dst_run), self._dst_stmt_idx) else: next_expr = self._get_irsb(self._dst_run).next if type(next_expr) is pyvex.IRExpr.RdTmp: temps.add(next_expr.tmp) elif type(next_expr) is pyvex.IRExpr.Const: # A const doesn't rely on anything else! pass else: raise AngrBladeError('Unsupported type for irsb.next: %s' % type(next_expr)) # Then we gotta start from the very last statement! self._dst_stmt_idx = len(stmts) - 1 prev = (self._get_addr(self._dst_run), 'default') slicer = simuvex.SimSlicer(self.project.arch, stmts, target_tmps=temps, target_regs=regs, target_stack_offsets=None, inslice_callback=self._inslice_callback, inslice_callback_infodict={ 'irsb_addr': self._get_irsb(self._dst_run)._addr, 'prev': prev, }) regs = slicer.final_regs if self._ignore_sp and self.project.arch.sp_offset in regs: regs.remove(self.project.arch.sp_offset) if self._ignore_bp and self.project.arch.bp_offset in regs: regs.remove(self.project.arch.bp_offset) for offset in self._ignored_regs: if offset in regs: regs.remove(offset) stack_offsets = slicer.final_stack_offsets prev = slicer.inslice_callback_infodict['prev'] if regs or stack_offsets: cfgnode = self._get_cfgnode(self._dst_run) in_edges = self._graph.in_edges(cfgnode, data=True) for pred, _, data in in_edges: if pred not in self._traced_runs: self._traced_runs.add(pred) self._backward_slice_recursive(self._max_level - 1, pred, regs, stack_offsets, prev, data['stmt_idx'])