[docs]classProcedureMixin:""" A mixin for SimEngine which adds the ``process_procedure`` method for calling a SimProcedure and adding its results to a SimSuccessors. """
[docs]defprocess_procedure(self,state,successors,procedure,ret_to=None,arguments=None,**kwargs):successors.sort="SimProcedure"# fill in artifactssuccessors.artifacts["is_syscall"]=procedure.is_syscallsuccessors.artifacts["name"]=procedure.display_namesuccessors.artifacts["no_ret"]=procedure.NO_RETsuccessors.artifacts["adds_exits"]=procedure.ADDS_EXITS# Update state.scratchstate.scratch.sim_procedure=procedurestate.history.recent_block_count=1# prepare and run!ifprocedure.is_syscall:state._inspect("syscall",BP_BEFORE,syscall_name=procedure.display_name)cleanup_options=o.AUTO_REFSnotinstate.optionsando.ADD_AUTO_REFSinstate.optionsifcleanup_options:state.options.add(o.AST_DEPS)state.options.add(o.AUTO_REFS)# do itinst=procedure.execute(state,successors,ret_to=ret_to,arguments=arguments)successors.artifacts["procedure"]=instifcleanup_options:state.options.discard(o.AST_DEPS)state.options.discard(o.AUTO_REFS)ifprocedure.is_syscall:state._inspect("syscall",BP_AFTER,syscall_name=procedure.display_name,simprocedure=inst)successors.description="SimProcedure "+procedure.display_nameifprocedure.is_syscall:successors.description+=" (syscall)"ifprocedure.is_stub:successors.description+=" (stub)"successors.processed=True
[docs]classProcedureEngine(ProcedureMixin,SuccessorsMixin):""" A SimEngine that you may use if you only care about processing SimProcedures. *Requires* the procedure kwarg to be passed to process. """
[docs]defprocess_successors(self,successors,procedure=None,**kwargs):ifprocedureisNone:raiseerrors.SimEngineError("Must provide the procedure explicitly to use ProcedureEngine")self.process_procedure(self.state,successors,procedure,**kwargs)