(self, function_manager, addr, name=None, syscall=None, is_simprocedure=None, binary_name=None,
                 is_plt=None, returning=None, alignment=False)
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.
        :param bool alignment:  If this function acts as an alignment filler. Such functions usually only contain nops.
Function constructor. If the optional parameters are not provided, they will be automatically determined upon
        the creation of a Function object.
Function constructor . If the optional parameters are not provided they will be automatically determined upon the creation of a Function object .
def __init__(self, function_manager, addr, name=None, syscall=None, is_simprocedure=None, binary_name=None,
                 is_plt=None, returning=None, alignment=False):
        """
        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.
        :param bool alignment:  If this function acts as an alignment filler. Such functions usually only contain nops.
        """
        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
        self.alignment = alignment

        # 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  # type: Optional[SimCC]
        # Function prototype
        self.prototype = None  # type: Optional[SimTypeFunction]
        self.is_prototype_guessed: bool = True
        # 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. it's a cache of blocks. if a block is removed from the
                                       # function, it may not be removed from _addr_to_block_node. if you want to list
                                       # all blocks of a function, access .blocks.
        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  # type: Optional[Project] # 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.is_default_name = False
            self._name = name
        self.from_signature = None

        # 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:
            simproc = self.project._sim_procedures[self.addr]
            cc = simproc.cc
            if cc is None:
                arch = self.project.arch
                if self.project.arch.name in DEFAULT_CC:
                    cc = DEFAULT_CC[arch.name](arch)

            self.calling_convention = 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 , alignment = False ) : 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 self . alignment = alignment # 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 # type: Optional[SimCC] # Function prototype self . prototype = None # type: Optional[SimTypeFunction] self . is_prototype_guessed : bool = True # 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. it's a cache of blocks. if a block is removed from the # function, it may not be removed from _addr_to_block_node. if you want to list # all blocks of a function, access .blocks. 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 # type: Optional[Project] # 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 . is_default_name = False self . _name = name self . from_signature = None # 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 : simproc = self . project . _sim_procedures [ self . addr ] cc = simproc . cc if cc is None : arch = self . project . arch if self . project . arch . name in DEFAULT_CC : cc = DEFAULT_CC [ arch . name ] ( arch ) self . calling_convention = cc else : self . calling_convention = None