(self, cfg_job, current_func_addr)
return entries
Generate a list of successors (generating them each as entries) to IRSB.
        Updates previous CFG nodes with edges.

        :param CFGJob cfg_job: The CFGJob instance.
        :param int current_func_addr: Address of the current function
        :return: a list of successors
        :rtype: list
Generate a list of successors (generating them each as entries) to IRSB.
        Updates previous CFG nodes with edges.
Generate a list of successors ( generating them each as entries ) to IRSB . Updates previous CFG nodes with edges .
def _scan_irsb(self, cfg_job, current_func_addr):
        """
        Generate a list of successors (generating them each as entries) to IRSB.
        Updates previous CFG nodes with edges.

        :param CFGJob cfg_job: The CFGJob instance.
        :param int current_func_addr: Address of the current function
        :return: a list of successors
        :rtype: list
        """
        addr, function_addr, cfg_node, irsb = self._generate_cfgnode(cfg_job, current_func_addr)

        # function_addr and current_function_addr can be different. e.g. when tracing an optimized tail-call that jumps
        # into another function that has been identified before.

        if cfg_node is None:
            # exceptions occurred, or we cannot get a CFGNode for other reasons
            return [ ]

        # Add edges going to this node in function graphs
        cfg_job.apply_function_edges(self, clear=True)

        self._graph_add_edge(cfg_node, cfg_job.src_node, cfg_job.jumpkind, cfg_job.src_ins_addr,
                             cfg_job.src_stmt_idx
                             )
        self._function_add_node(cfg_node, function_addr)

        if self.functions.get_by_addr(function_addr).returning is not True:
            self._updated_nonreturning_functions.add(function_addr)

        # If we have traced it before, don't trace it anymore
        real_addr = get_real_address_if_arm(self.project.arch, addr)
        if real_addr in self._traced_addresses:
            # the address has been traced before
            return [ ]
        else:
            # Mark the address as traced
            self._traced_addresses.add(real_addr)

        # irsb cannot be None here
        # assert irsb is not None

        # IRSB is only used once per CFGNode. We should be able to clean up the CFGNode here in order to save memory
        cfg_node.irsb = None

        caller_gp = None
        if self.project.arch.name in {'MIPS32', 'MIPS64'}:
            # the caller might have gp passed on
            caller_gp = cfg_job.gp
        self._process_block_arch_specific(addr, irsb, function_addr, caller_gp=caller_gp)

        # Scan the basic block to collect data references
        if self._collect_data_ref:
            self._collect_data_references(irsb, addr)

        # Get all possible successors
        irsb_next, jumpkind = irsb.next, irsb.jumpkind
        successors = [ ]

        if irsb.statements:
            last_ins_addr = None
            ins_addr = addr
            for i, stmt in enumerate(irsb.statements):
                if isinstance(stmt, pyvex.IRStmt.Exit):
                    successors.append((i,
                                       last_ins_addr if self.project.arch.branch_delay_slot else ins_addr,
                                       stmt.dst,
                                       stmt.jumpkind
                                       )
                                      )
                elif isinstance(stmt, pyvex.IRStmt.IMark):
                    last_ins_addr = ins_addr
                    ins_addr = stmt.addr + stmt.delta
        else:
            for ins_addr, stmt_idx, exit_stmt in irsb.exit_statements:
                branch_ins_addr = ins_addr
                if self.project.arch.branch_delay_slot \
                        and irsb.instruction_addresses \
                        and ins_addr in irsb.instruction_addresses:
                    idx_ = irsb.instruction_addresses.index(ins_addr)
                    if idx_ > 0:
                        branch_ins_addr = irsb.instruction_addresses[idx_ - 1]
                successors.append((
                    stmt_idx,
                    branch_ins_addr,
                    exit_stmt.dst,
                    exit_stmt.jumpkind
                ))

        # default statement
        default_branch_ins_addr = None
        if irsb.instruction_addresses:
            if self.project.arch.branch_delay_slot:
                if len(irsb.instruction_addresses) > 1:
                    default_branch_ins_addr = irsb.instruction_addresses[-2]
            else:
                default_branch_ins_addr = irsb.instruction_addresses[-1]

        successors.append((DEFAULT_STATEMENT, default_branch_ins_addr, irsb_next, jumpkind))

        # exception handling
        exc = self._exception_handling_by_endaddr.get(addr + irsb.size, None)
        if exc is not None:
            successors.append(
                (DEFAULT_STATEMENT,
                 default_branch_ins_addr,
                 exc.handler_addr,
                 'Ijk_Exception')
            )

        entries = [ ]

        successors = self._post_process_successors(irsb, successors)

        # Process each successor
        for suc in successors:
            stmt_idx, ins_addr, target, jumpkind = suc

            entries += self._create_jobs(target, jumpkind, function_addr, irsb, addr, cfg_node, ins_addr,
                                         stmt_idx
                                         )

        return entries
def _scan_irsb ( self , cfg_job , current_func_addr ) : addr , function_addr , cfg_node , irsb = self . _generate_cfgnode ( cfg_job , current_func_addr ) # function_addr and current_function_addr can be different. e.g. when tracing an optimized tail-call that jumps # into another function that has been identified before. if cfg_node is None : # exceptions occurred, or we cannot get a CFGNode for other reasons return [ ] # Add edges going to this node in function graphs cfg_job . apply_function_edges ( self , clear = True ) self . _graph_add_edge ( cfg_node , cfg_job . src_node , cfg_job . jumpkind , cfg_job . src_ins_addr , cfg_job . src_stmt_idx ) self . _function_add_node ( cfg_node , function_addr ) if self . functions . get_by_addr ( function_addr ) . returning is not True : self . _updated_nonreturning_functions . add ( function_addr ) # If we have traced it before, don't trace it anymore real_addr = get_real_address_if_arm ( self . project . arch , addr ) if real_addr in self . _traced_addresses : # the address has been traced before return [ ] else : # Mark the address as traced self . _traced_addresses . add ( real_addr ) # irsb cannot be None here # assert irsb is not None # IRSB is only used once per CFGNode. We should be able to clean up the CFGNode here in order to save memory cfg_node . irsb = None caller_gp = None if self . project . arch . name in { 'MIPS32' , 'MIPS64' } : # the caller might have gp passed on caller_gp = cfg_job . gp self . _process_block_arch_specific ( addr , irsb , function_addr , caller_gp = caller_gp ) # Scan the basic block to collect data references if self . _collect_data_ref : self . _collect_data_references ( irsb , addr ) # Get all possible successors irsb_next , jumpkind = irsb . next , irsb . jumpkind successors = [ ] if irsb . statements : last_ins_addr = None ins_addr = addr for i , stmt in enumerate ( irsb . statements ) : if isinstance ( stmt , pyvex . IRStmt . Exit ) : successors . append ( ( i , last_ins_addr if self . project . arch . branch_delay_slot else ins_addr , stmt . dst , stmt . jumpkind ) ) elif isinstance ( stmt , pyvex . IRStmt . IMark ) : last_ins_addr = ins_addr ins_addr = stmt . addr + stmt . delta else : for ins_addr , stmt_idx , exit_stmt in irsb . exit_statements : branch_ins_addr = ins_addr if self . project . arch . branch_delay_slot and irsb . instruction_addresses and ins_addr in irsb . instruction_addresses : idx_ = irsb . instruction_addresses . index ( ins_addr ) if idx_ > 0 : branch_ins_addr = irsb . instruction_addresses [ idx_ - 1 ] successors . append ( ( stmt_idx , branch_ins_addr , exit_stmt . dst , exit_stmt . jumpkind ) ) # default statement default_branch_ins_addr = None if irsb . instruction_addresses : if self . project . arch . branch_delay_slot : if len ( irsb . instruction_addresses ) > 1 : default_branch_ins_addr = irsb . instruction_addresses [ - 2 ] else : default_branch_ins_addr = irsb . instruction_addresses [ - 1 ] successors . append ( ( DEFAULT_STATEMENT , default_branch_ins_addr , irsb_next , jumpkind ) ) # exception handling exc = self . _exception_handling_by_endaddr . get ( addr + irsb . size , None ) if exc is not None : successors . append ( ( DEFAULT_STATEMENT , default_branch_ins_addr , exc . handler_addr , 'Ijk_Exception' ) ) entries = [ ] successors = self . _post_process_successors ( irsb , successors ) # Process each successor for suc in successors : stmt_idx , ins_addr , target , jumpkind = suc entries += self . _create_jobs ( target , jumpkind , function_addr , irsb , addr , cfg_node , ins_addr , stmt_idx ) return entries