def __init__(self, function_manager, addr, name=None, syscall=None, is_simprocedure=None, binary_name=None,
                 is_plt=None, returning=None):
        """
        Function constructor. If the optional parameters are not provided, they will be automatically determined upon
        the creation of a Function object.

        :param addr:            The address of the function.

        The following parameters are optional.

        :param str name:        The name of the function.
        :param bool syscall:    Whether this function is a syscall or not.
        :param bool is_simprocedure:    Whether this function is a SimProcedure or not.
        :param str binary_name: Name of the binary where this function is.
        :param bool is_plt:     If this function is a PLT entry.
        :param bool returning:  If this function returns.
        """
        self.transition_graph = networkx.DiGraph()
        self._local_transition_graph = None
        self.normalized = False

        # block nodes at whose ends the function returns
        self._ret_sites = set()
        # block nodes at whose ends the function jumps out to another function (jumps outside)
        self._jumpout_sites = set()
        # block nodes at whose ends the function calls out to another non-returning function
        self._callout_sites = set()
        # block nodes that ends the function by returning out to another function (returns outside). This is rare.
        self._retout_sites = set()
        # block nodes (basic block nodes) at whose ends the function terminates
        # in theory, if everything works fine, endpoints == ret_sites | jumpout_sites | callout_sites
        self._endpoints = defaultdict(set)

        self._call_sites = {}
        self.addr = addr
        # startpoint can be None if the corresponding CFGNode is a syscall node
        self.startpoint = None
        self._function_manager = function_manager
        self.is_syscall = None
        self.is_plt = None
        self.is_simprocedure = False

        # These properties are set by VariableManager
        self.bp_on_stack = False
        self.retaddr_on_stack = False
        self.sp_delta = 0
        # Calling convention
        self.calling_convention = None
        # Function prototype
        self.prototype = None
        # Whether this function returns or not. `None` means it's not determined yet
        self._returning = None

        self.prepared_registers = set()
        self.prepared_stack_variables = set()
        self.registers_read_afterwards = set()

        self._addr_to_block_node = {}  # map addresses to nodes
        self._block_sizes = {}  # map addresses to block sizes
        self._block_cache = {}  # a cache of real, hard data Block objects
        self._local_blocks = {}  # a dict of all blocks inside the function
        self._local_block_addrs = set()  # a set of addresses of all blocks inside the function

        self.info = {}  # storing special information, like $gp values for MIPS32
        self.tags = tuple()  # store function tags. can be set manually by performing CodeTagging analysis.

        # TODO: Can we remove the following two members?
        # Register offsets of those arguments passed in registers
        self._argument_registers = []
        # Stack offsets of those arguments passed in stack variables
        self._argument_stack_variables = []

        self._project = None  # will be initialized upon the first access to self.project

        #
        # Initialize unspecified properties
        #

        if syscall is not None:
            self.is_syscall = syscall
        else:
            if self.project is None:
                raise ValueError("'syscall' must be specified if you do not specify a function manager for this new"
                                 " function." )

            # Determine whether this function is a syscall or not
            self.is_syscall = self.project.simos.is_syscall_addr(addr)

        # Determine whether this function is a SimProcedure
        if is_simprocedure is not None:
            self.is_simprocedure = is_simprocedure
        else:
            if self.project is None:
                raise ValueError("'is_simprocedure' must be specified if you do not specify a function manager for this"
                                 " new function.")

            if self.is_syscall or self.project.is_hooked(addr):
                self.is_simprocedure = True

        # Determine if this function is a PLT entry
        if is_plt is not None:
            self.is_plt = is_plt
        else:
            # Whether this function is a PLT entry or not is fully relying on the PLT detection in CLE
            if self.project is None:
                raise ValueError("'is_plt' must be specified if you do not specify a function manager for this new"
                                 " function.")

            self.is_plt = self.project.loader.find_plt_stub_name(addr) is not None

        # Determine the name of this function
        if name is None:
            self._name = self._get_initial_name()
        else:
            self._name = name

        # Determine the name the binary where this function is.
        if binary_name is not None:
            self.binary_name = binary_name
        else:
            self.binary_name = self._get_initial_binary_name()

        # Determine returning status for SimProcedures and Syscalls
        if returning is not None:
            self._returning = returning
        else:
            if self.project is None:
                raise ValueError("'returning' must be specified if you do not specify a functio nmnager for this new"
                                 " function.")

            self._returning = self._get_initial_returning()

        # Determine a calling convention
        # If it is a SimProcedure it might have a CC already defined which can be used
        if self.is_simprocedure and self.project is not None and self.addr in self.project._sim_procedures:
            self.calling_convention = self.project._sim_procedures[self.addr].cc
        else:
            self.calling_convention = None
def __init__ ( self , function_manager , addr , name = None , syscall = None , is_simprocedure = None , binary_name = None , is_plt = None , returning = None ) : self . transition_graph = networkx . DiGraph ( ) self . _local_transition_graph = None self . normalized = False self . _ret_sites = set ( ) self . _jumpout_sites = set ( ) self . _callout_sites = set ( ) self . _retout_sites = set ( ) self . _endpoints = defaultdict ( set ) self . _call_sites = { } self . addr = addr self . startpoint = None self . _function_manager = function_manager self . is_syscall = None self . is_plt = None self . is_simprocedure = False self . bp_on_stack = False self . retaddr_on_stack = False self . sp_delta = 0 self . calling_convention = None self . prototype = None self . _returning = None self . prepared_registers = set ( ) self . prepared_stack_variables = set ( ) self . registers_read_afterwards = set ( ) self . _addr_to_block_node = { } self . _block_sizes = { } self . _block_cache = { } self . _local_blocks = { } self . _local_block_addrs = set ( ) self . info = { } self . tags = tuple ( ) self . _argument_registers = [ ] self . _argument_stack_variables = [ ] self . _project = None if syscall is not None : self . is_syscall = syscall else : if self . project is None : raise ValueError ( "'syscall' must be specified if you do not specify a function manager for this new" " function." ) self . is_syscall = self . project . simos . is_syscall_addr ( addr ) if is_simprocedure is not None : self . is_simprocedure = is_simprocedure else : if self . project is None : raise ValueError ( "'is_simprocedure' must be specified if you do not specify a function manager for this" " new function." ) if self . is_syscall or self . project . is_hooked ( addr ) : self . is_simprocedure = True if is_plt is not None : self . is_plt = is_plt else : if self . project is None : raise ValueError ( "'is_plt' must be specified if you do not specify a function manager for this new" " function." ) self . is_plt = self . project . loader . find_plt_stub_name ( addr ) is not None if name is None : self . _name = self . _get_initial_name ( ) else : self . _name = name if binary_name is not None : self . binary_name = binary_name else : self . binary_name = self . _get_initial_binary_name ( ) if returning is not None : self . _returning = returning else : if self . project is None : raise ValueError ( "'returning' must be specified if you do not specify a functio nmnager for this new" " function." ) self . _returning = self . _get_initial_returning ( ) if self . is_simprocedure and self . project is not None and self . addr in self . project . _sim_procedures : self . calling_convention = self . project . _sim_procedures [ self . addr ] . cc else : self . calling_convention = None
Function constructor. If the optional parameters are not provided, they will be automatically determined upon
        the creation of a Function object.

        :param addr:            The address of the function.

        The following parameters are optional.

        :param str name:        The name of the function.
        :param bool syscall:    Whether this function is a syscall or not.
        :param bool is_simprocedure:    Whether this function is a SimProcedure or not.
        :param str binary_name: Name of the binary where this function is.
        :param bool is_plt:     If this function is a PLT entry.
        :param bool returning:  If this function returns.