(self, addr, job, current_function_addr=None)
return sim_successors, exception_info, saved_state
Create the SimSuccessors instance for a block.

        :param int addr:                  Address of the block.
        :param CFGJob job:                The CFG job instance with an input state inside.
        :param int current_function_addr: Address of the current function.
        :return:                          A SimSuccessors instance
        :rtype:                           SimSuccessors
Create the SimSuccessors instance for a block.
Create the SimSuccessors instance for a block .
def _get_simsuccessors(self, addr, job, current_function_addr=None):
        """
        Create the SimSuccessors instance for a block.

        :param int addr:                  Address of the block.
        :param CFGJob job:                The CFG job instance with an input state inside.
        :param int current_function_addr: Address of the current function.
        :return:                          A SimSuccessors instance
        :rtype:                           SimSuccessors
        """

        exception_info = None
        state = job.state
        saved_state = job.state  # We don't have to make a copy here

        # respect the basic block size from base graph
        block_size = None
        if self._base_graph is not None:
            for n in self._base_graph.nodes():
                if n.addr == addr:
                    block_size = n.size
                    break

        try:
            sim_successors = None

            if not self._keep_state:
                if self.project.is_hooked(addr):
                    old_proc = self.project._sim_procedures[addr]
                    is_continuation = old_proc.is_continuation
                elif self.project.simos.is_syscall_addr(addr):
                    old_proc = self.project.simos.syscall_from_addr(addr)
                    is_continuation = False  # syscalls don't support continuation
                else:
                    old_proc = None
                    is_continuation = None

                if old_proc is not None and \
                        not is_continuation and \
                        not old_proc.ADDS_EXITS and \
                        not old_proc.NO_RET:
                    # DON'T CREATE USELESS SIMPROCEDURES if we don't care about the accuracy of states
                    # When generating CFG, a SimProcedure will not be created as it is but be created as a
                    # ReturnUnconstrained stub if it satisfies the following conditions:
                    # - It doesn't add any new exits.
                    # - It returns as normal.
                    # In this way, we can speed up the CFG generation by quite a lot as we avoid simulating
                    # those functions like read() and puts(), which has no impact on the overall control flow at all.
                    #
                    # Special notes about SimProcedure continuation: Any SimProcedure instance that is a continuation
                    # will add new exits, otherwise the original SimProcedure wouldn't have been executed anyway. Hence
                    # it's reasonable for us to always simulate a SimProcedure with continuation.

                    old_name = None

                    if old_proc.is_syscall:
                        new_stub = SIM_PROCEDURES["stubs"]["syscall"]
                        ret_to = state.regs.ip_at_syscall
                    else:
                        # normal SimProcedures
                        new_stub = SIM_PROCEDURES["stubs"]["ReturnUnconstrained"]
                        ret_to = None

                    old_name = old_proc.display_name

                    # instantiate the stub
                    new_stub_inst = new_stub(display_name=old_name)

                    sim_successors = self.project.factory.procedure_engine.process(
                        state,
                        procedure=new_stub_inst,
                        force_addr=addr,
                        ret_to=ret_to,
                    )

            if sim_successors is None:
                jumpkind = state.history.jumpkind
                jumpkind = 'Ijk_Boring' if jumpkind is None else jumpkind
                sim_successors = self.project.factory.successors(
                        state,
                        jumpkind=jumpkind,
                        size=block_size,
                        opt_level=self._iropt_level)

        except (SimFastPathError, SimSolverModeError) as ex:

            if saved_state.mode == 'fastpath':
                # Got a SimFastPathError or SimSolverModeError in FastPath mode.
                # We wanna switch to symbolic mode for current IRSB.
                l.debug('Switch to symbolic mode for address %#x', addr)
                # Make a copy of the current 'fastpath' state

                l.debug('Symbolic jumps at basic block %#x.', addr)

                new_state = None
                if addr != current_function_addr:
                    new_state = self._get_symbolic_function_initial_state(current_function_addr)

                if new_state is None:
                    new_state = state.copy()
                    new_state.set_mode('symbolic')
                new_state.options.add(o.DO_RET_EMULATION)
                # Remove bad constraints
                # FIXME: This is so hackish...
                new_state.solver._solver.constraints = [c for c in new_state.solver.constraints if
                                                    c.op != 'BoolV' or c.args[0] is not False]
                new_state.solver._solver._result = None
                # Swap them
                saved_state, job.state = job.state, new_state
                sim_successors, exception_info, _ = self._get_simsuccessors(addr, job)

            else:
                exception_info = sys.exc_info()
                # Got a SimSolverModeError in symbolic mode. We are screwed.
                # Skip this IRSB
                l.debug("Caught a SimIRSBError %s. Don't panic, this is usually expected.", ex)
                inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
                sim_successors = ProcedureEngine().process(state, procedure=inst)

        except SimIRSBError:
            exception_info = sys.exc_info()
            # It's a tragedy that we came across some instructions that VEX
            # does not support. I'll create a terminating stub there
            l.debug("Caught a SimIRSBError during CFG recovery. Creating a PathTerminator.", exc_info=True)
            inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
            sim_successors = ProcedureEngine().process(state, procedure=inst)

        except claripy.ClaripyError:
            exception_info = sys.exc_info()
            l.debug("Caught a ClaripyError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
            # Generate a PathTerminator to terminate the current path
            inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
            sim_successors = ProcedureEngine().process(state, procedure=inst)

        except SimError:
            exception_info = sys.exc_info()
            l.debug("Caught a SimError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
            # Generate a PathTerminator to terminate the current path
            inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
            sim_successors = ProcedureEngine().process(state, procedure=inst)

        except AngrExitError as ex:
            exception_info = sys.exc_info()
            l.debug("Caught a AngrExitError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
            # Generate a PathTerminator to terminate the current path
            inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
            sim_successors = ProcedureEngine().process(state, procedure=inst)

        except AngrError:
            exception_info = sys.exc_info()
            section = self.project.loader.main_object.find_section_containing(addr)
            if section is None:
                sec_name = 'No section'
            else:
                sec_name = section.name
            # AngrError shouldn't really happen though
            l.debug("Caught an AngrError during CFG recovery at %#x (%s)",
                    addr, sec_name, exc_info=True)
            # We might be on a wrong branch, and is likely to encounter the
            # "No bytes in memory xxx" exception
            # Just ignore it
            sim_successors = None

        return sim_successors, exception_info, saved_state
def _get_simsuccessors ( self , addr , job , current_function_addr = None ) : exception_info = None state = job . state saved_state = job . state # We don't have to make a copy here # respect the basic block size from base graph block_size = None if self . _base_graph is not None : for n in self . _base_graph . nodes ( ) : if n . addr == addr : block_size = n . size break try : sim_successors = None if not self . _keep_state : if self . project . is_hooked ( addr ) : old_proc = self . project . _sim_procedures [ addr ] is_continuation = old_proc . is_continuation elif self . project . simos . is_syscall_addr ( addr ) : old_proc = self . project . simos . syscall_from_addr ( addr ) is_continuation = False # syscalls don't support continuation else : old_proc = None is_continuation = None if old_proc is not None and not is_continuation and not old_proc . ADDS_EXITS and not old_proc . NO_RET : # DON'T CREATE USELESS SIMPROCEDURES if we don't care about the accuracy of states # When generating CFG, a SimProcedure will not be created as it is but be created as a # ReturnUnconstrained stub if it satisfies the following conditions: # - It doesn't add any new exits. # - It returns as normal. # In this way, we can speed up the CFG generation by quite a lot as we avoid simulating # those functions like read() and puts(), which has no impact on the overall control flow at all. # # Special notes about SimProcedure continuation: Any SimProcedure instance that is a continuation # will add new exits, otherwise the original SimProcedure wouldn't have been executed anyway. Hence # it's reasonable for us to always simulate a SimProcedure with continuation. old_name = None if old_proc . is_syscall : new_stub = SIM_PROCEDURES [ "stubs" ] [ "syscall" ] ret_to = state . regs . ip_at_syscall else : # normal SimProcedures new_stub = SIM_PROCEDURES [ "stubs" ] [ "ReturnUnconstrained" ] ret_to = None old_name = old_proc . display_name # instantiate the stub new_stub_inst = new_stub ( display_name = old_name ) sim_successors = self . project . factory . procedure_engine . process ( state , procedure = new_stub_inst , force_addr = addr , ret_to = ret_to , ) if sim_successors is None : jumpkind = state . history . jumpkind jumpkind = 'Ijk_Boring' if jumpkind is None else jumpkind sim_successors = self . project . factory . successors ( state , jumpkind = jumpkind , size = block_size , opt_level = self . _iropt_level ) except ( SimFastPathError , SimSolverModeError ) as ex : if saved_state . mode == 'fastpath' : # Got a SimFastPathError or SimSolverModeError in FastPath mode. # We wanna switch to symbolic mode for current IRSB. l . debug ( 'Switch to symbolic mode for address %#x' , addr ) # Make a copy of the current 'fastpath' state l . debug ( 'Symbolic jumps at basic block %#x.' , addr ) new_state = None if addr != current_function_addr : new_state = self . _get_symbolic_function_initial_state ( current_function_addr ) if new_state is None : new_state = state . copy ( ) new_state . set_mode ( 'symbolic' ) new_state . options . add ( o . DO_RET_EMULATION ) # Remove bad constraints # FIXME: This is so hackish... new_state . solver . _solver . constraints = [ c for c in new_state . solver . constraints if c . op != 'BoolV' or c . args [ 0 ] is not False ] new_state . solver . _solver . _result = None # Swap them saved_state , job . state = job . state , new_state sim_successors , exception_info , _ = self . _get_simsuccessors ( addr , job ) else : exception_info = sys . exc_info ( ) # Got a SimSolverModeError in symbolic mode. We are screwed. # Skip this IRSB l . debug ( "Caught a SimIRSBError %s. Don't panic, this is usually expected." , ex ) inst = SIM_PROCEDURES [ "stubs" ] [ "PathTerminator" ] ( ) sim_successors = ProcedureEngine ( ) . process ( state , procedure = inst ) except SimIRSBError : exception_info = sys . exc_info ( ) # It's a tragedy that we came across some instructions that VEX # does not support. I'll create a terminating stub there l . debug ( "Caught a SimIRSBError during CFG recovery. Creating a PathTerminator." , exc_info = True ) inst = SIM_PROCEDURES [ "stubs" ] [ "PathTerminator" ] ( ) sim_successors = ProcedureEngine ( ) . process ( state , procedure = inst ) except claripy . ClaripyError : exception_info = sys . exc_info ( ) l . debug ( "Caught a ClaripyError during CFG recovery. Don't panic, this is usually expected." , exc_info = True ) # Generate a PathTerminator to terminate the current path inst = SIM_PROCEDURES [ "stubs" ] [ "PathTerminator" ] ( ) sim_successors = ProcedureEngine ( ) . process ( state , procedure = inst ) except SimError : exception_info = sys . exc_info ( ) l . debug ( "Caught a SimError during CFG recovery. Don't panic, this is usually expected." , exc_info = True ) # Generate a PathTerminator to terminate the current path inst = SIM_PROCEDURES [ "stubs" ] [ "PathTerminator" ] ( ) sim_successors = ProcedureEngine ( ) . process ( state , procedure = inst ) except AngrExitError as ex : exception_info = sys . exc_info ( ) l . debug ( "Caught a AngrExitError during CFG recovery. Don't panic, this is usually expected." , exc_info = True ) # Generate a PathTerminator to terminate the current path inst = SIM_PROCEDURES [ "stubs" ] [ "PathTerminator" ] ( ) sim_successors = ProcedureEngine ( ) . process ( state , procedure = inst ) except AngrError : exception_info = sys . exc_info ( ) section = self . project . loader . main_object . find_section_containing ( addr ) if section is None : sec_name = 'No section' else : sec_name = section . name # AngrError shouldn't really happen though l . debug ( "Caught an AngrError during CFG recovery at %#x (%s)" , addr , sec_name , exc_info = True ) # We might be on a wrong branch, and is likely to encounter the # "No bytes in memory xxx" exception # Just ignore it sim_successors = None return sim_successors , exception_info , saved_state