(self)
For each returning function, create return edges in self.graph.

        :return: None
For each returning function, create return edges in self.graph.
For each returning function create return edges in self . graph .
def _make_return_edges(self):
        """
        For each returning function, create return edges in self.graph.

        :return: None
        """

        for func_addr, func in self.functions.items():
            if func.returning is False:
                continue

            # get the node on CFG
            if func.startpoint is None:
                l.warning('Function %#x does not have a startpoint (yet).', func_addr)
                continue

            startpoint = self.model.get_any_node(func.startpoint.addr)
            if startpoint is None:
                # weird...
                l.warning('No CFGNode is found for function %#x in _make_return_edges().', func_addr)
                continue

            endpoints = self._get_return_sources(func)

            # get all callers
            callers = self.model.get_predecessors(startpoint, jumpkind='Ijk_Call')

            # handle callers for tailcall optimizations if flag is enabled
            if self._detect_tail_calls and startpoint.addr in self._tail_calls:
                l.debug("Handling return address for tail call for func %x", func_addr)
                seen = set()
                tail_callers = self._get_tail_caller(startpoint, seen)
                callers.extend(tail_callers)

            # for each caller, since they all end with a call instruction, get the immediate successor
            return_targets = itertools.chain.from_iterable(
                self.model.get_successors(caller, excluding_fakeret=False, jumpkind='Ijk_FakeRet') for caller in callers
            )
            return_targets = set(return_targets)

            for ep in endpoints:
                src = self.model.get_any_node(ep.addr)
                for rt in return_targets:
                    if not src.instruction_addrs:
                        ins_addr = None
                    else:
                        if self.project.arch.branch_delay_slot:
                            if len(src.instruction_addrs) > 1:
                                ins_addr = src.instruction_addrs[-2]
                            else:
                                l.error('At %s: expecting more than one instruction. Only got one.', src)
                                ins_addr = None
                        else:
                            ins_addr = src.instruction_addrs[-1]

                    self._graph_add_edge(rt, src, 'Ijk_Ret', ins_addr, DEFAULT_STATEMENT)
def _make_return_edges ( self ) : for func_addr , func in self . functions . items ( ) : if func . returning is False : continue # get the node on CFG if func . startpoint is None : l . warning ( 'Function %#x does not have a startpoint (yet).' , func_addr ) continue startpoint = self . model . get_any_node ( func . startpoint . addr ) if startpoint is None : # weird... l . warning ( 'No CFGNode is found for function %#x in _make_return_edges().' , func_addr ) continue endpoints = self . _get_return_sources ( func ) # get all callers callers = self . model . get_predecessors ( startpoint , jumpkind = 'Ijk_Call' ) # handle callers for tailcall optimizations if flag is enabled if self . _detect_tail_calls and startpoint . addr in self . _tail_calls : l . debug ( "Handling return address for tail call for func %x" , func_addr ) seen = set ( ) tail_callers = self . _get_tail_caller ( startpoint , seen ) callers . extend ( tail_callers ) # for each caller, since they all end with a call instruction, get the immediate successor return_targets = itertools . chain . from_iterable ( self . model . get_successors ( caller , excluding_fakeret = False , jumpkind = 'Ijk_FakeRet' ) for caller in callers ) return_targets = set ( return_targets ) for ep in endpoints : src = self . model . get_any_node ( ep . addr ) for rt in return_targets : if not src . instruction_addrs : ins_addr = None else : if self . project . arch . branch_delay_slot : if len ( src . instruction_addrs ) > 1 : ins_addr = src . instruction_addrs [ - 2 ] else : l . error ( 'At %s: expecting more than one instruction. Only got one.' , src ) ins_addr = None else : ins_addr = src . instruction_addrs [ - 1 ] self . _graph_add_edge ( rt , src , 'Ijk_Ret' , ins_addr , DEFAULT_STATEMENT )