(self, src_node_key, dst_node_key, jumpkind='Ijk_Boring', ins_addr=None,
                                          stmt_idx=None, confirmed=None)
Update transition graphs of functions in function manager based on information passed in.

        :param src_node_key:    Node key of the source CFGNode. Might be None.
        :param dst_node:        Node key of the destination CFGNode. Might be None.
        :param str jumpkind:    Jump kind of this transition.
        :param int ret_addr:    The theoretical return address for calls.
        :param int or None ins_addr:    Address of the instruction where this transition is made.
        :param int or None stmt_idx:    ID of the statement where this transition is made.
        :param bool or None confirmed:  Whether this call transition has been confirmed or not.
        :return: None
Update transition graphs of functions in function manager based on information passed in.
Update transition graphs of functions in function manager based on information passed in .
def _update_function_transition_graph(self, src_node_key, dst_node_key, jumpkind='Ijk_Boring', ins_addr=None,
                                          stmt_idx=None, confirmed=None):
        """
        Update transition graphs of functions in function manager based on information passed in.

        :param src_node_key:    Node key of the source CFGNode. Might be None.
        :param dst_node:        Node key of the destination CFGNode. Might be None.
        :param str jumpkind:    Jump kind of this transition.
        :param int ret_addr:    The theoretical return address for calls.
        :param int or None ins_addr:    Address of the instruction where this transition is made.
        :param int or None stmt_idx:    ID of the statement where this transition is made.
        :param bool or None confirmed:  Whether this call transition has been confirmed or not.
        :return: None
        """

        if dst_node_key is not None:
            dst_node = self._graph_get_node(dst_node_key, terminator_for_nonexistent_node=True)
            dst_node_addr = dst_node.addr
            dst_codenode = dst_node.to_codenode()
            dst_node_func_addr = dst_node.function_address
        else:
            dst_node = None
            dst_node_addr = None
            dst_codenode = None
            dst_node_func_addr = None

        if src_node_key is None:
            if dst_node is None:
                raise ValueError("Either src_node_key or dst_node_key must be specified.")
            self.kb.functions.function(dst_node.function_address, create=True)._register_nodes(True,
                                                                                               dst_codenode
                                                                                               )
            return

        src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)

        # Update the transition graph of current function
        if jumpkind == "Ijk_Call":
            ret_addr = src_node.return_target
            ret_node = self.kb.functions.function(
                src_node.function_address,
                create=True
            )._get_block(ret_addr).codenode if ret_addr else None

            self.kb.functions._add_call_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_addr=dst_node_addr,
                retn_node=ret_node,
                syscall=False,
                ins_addr=ins_addr,
                stmt_idx=stmt_idx,
            )

        if jumpkind.startswith('Ijk_Sys'):

            self.kb.functions._add_call_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_addr=dst_node_addr,
                retn_node=src_node.to_codenode(),  # For syscalls, they are returning to the address of themselves
                syscall=True,
                ins_addr=ins_addr,
                stmt_idx=stmt_idx,
            )

        elif jumpkind == 'Ijk_Ret':
            # Create a return site for current function
            self.kb.functions._add_return_from(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_node=dst_codenode,
            )

            if dst_node is not None:
                # Create a returning edge in the caller function
                self.kb.functions._add_return_from_call(
                    function_addr=dst_node_func_addr,
                    src_function_addr=src_node.function_address,
                    to_node=dst_codenode,
                )

        elif jumpkind == 'Ijk_FakeRet':
            self.kb.functions._add_fakeret_to(
                function_addr=src_node.function_address,
                from_node=src_node.to_codenode(),
                to_node=dst_codenode,
                confirmed=confirmed,
            )

        elif jumpkind in ('Ijk_Boring', 'Ijk_InvalICache'):

            src_obj = self.project.loader.find_object_containing(src_node.addr)
            dest_obj = self.project.loader.find_object_containing(dst_node.addr) if dst_node is not None else None

            if src_obj is dest_obj:
                # Jump/branch within the same object. Might be an outside jump.
                to_outside = src_node.function_address != dst_node_func_addr
            else:
                # Jump/branch between different objects. Must be an outside jump.
                to_outside = True

            if not to_outside:
                self.kb.functions._add_transition_to(
                    function_addr=src_node.function_address,
                    from_node=src_node.to_codenode(),
                    to_node=dst_codenode,
                    ins_addr=ins_addr,
                    stmt_idx=stmt_idx,
                )

            else:
                self.kb.functions._add_outside_transition_to(
                    function_addr=src_node.function_address,
                    from_node=src_node.to_codenode(),
                    to_node=dst_codenode,
                    to_function_addr=dst_node_func_addr,
                    ins_addr=ins_addr,
                    stmt_idx=stmt_idx,
                )
def _update_function_transition_graph ( self , src_node_key , dst_node_key , jumpkind = 'Ijk_Boring' , ins_addr = None , stmt_idx = None , confirmed = None ) : if dst_node_key is not None : dst_node = self . _graph_get_node ( dst_node_key , terminator_for_nonexistent_node = True ) dst_node_addr = dst_node . addr dst_codenode = dst_node . to_codenode ( ) dst_node_func_addr = dst_node . function_address else : dst_node = None dst_node_addr = None dst_codenode = None dst_node_func_addr = None if src_node_key is None : if dst_node is None : raise ValueError ( "Either src_node_key or dst_node_key must be specified." ) self . kb . functions . function ( dst_node . function_address , create = True ) . _register_nodes ( True , dst_codenode ) return src_node = self . _graph_get_node ( src_node_key , terminator_for_nonexistent_node = True ) # Update the transition graph of current function if jumpkind == "Ijk_Call" : ret_addr = src_node . return_target ret_node = self . kb . functions . function ( src_node . function_address , create = True ) . _get_block ( ret_addr ) . codenode if ret_addr else None self . kb . functions . _add_call_to ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_addr = dst_node_addr , retn_node = ret_node , syscall = False , ins_addr = ins_addr , stmt_idx = stmt_idx , ) if jumpkind . startswith ( 'Ijk_Sys' ) : self . kb . functions . _add_call_to ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_addr = dst_node_addr , retn_node = src_node . to_codenode ( ) , # For syscalls, they are returning to the address of themselves syscall = True , ins_addr = ins_addr , stmt_idx = stmt_idx , ) elif jumpkind == 'Ijk_Ret' : # Create a return site for current function self . kb . functions . _add_return_from ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_node = dst_codenode , ) if dst_node is not None : # Create a returning edge in the caller function self . kb . functions . _add_return_from_call ( function_addr = dst_node_func_addr , src_function_addr = src_node . function_address , to_node = dst_codenode , ) elif jumpkind == 'Ijk_FakeRet' : self . kb . functions . _add_fakeret_to ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_node = dst_codenode , confirmed = confirmed , ) elif jumpkind in ( 'Ijk_Boring' , 'Ijk_InvalICache' ) : src_obj = self . project . loader . find_object_containing ( src_node . addr ) dest_obj = self . project . loader . find_object_containing ( dst_node . addr ) if dst_node is not None else None if src_obj is dest_obj : # Jump/branch within the same object. Might be an outside jump. to_outside = src_node . function_address != dst_node_func_addr else : # Jump/branch between different objects. Must be an outside jump. to_outside = True if not to_outside : self . kb . functions . _add_transition_to ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_node = dst_codenode , ins_addr = ins_addr , stmt_idx = stmt_idx , ) else : self . kb . functions . _add_outside_transition_to ( function_addr = src_node . function_address , from_node = src_node . to_codenode ( ) , to_node = dst_codenode , to_function_addr = dst_node_func_addr , ins_addr = ins_addr , stmt_idx = stmt_idx , )