(self)
Infer calling conventions for all functions in the current project.

        :return:
Infer calling conventions for all functions in the current project.
Infer calling conventions for all functions in the current project .
def _analyze(self):
        """
        Infer calling conventions for all functions in the current project.

        :return:
        """

        # get an ordering of functions based on the call graph
        sorted_funcs = CFGUtils.quasi_topological_sort_nodes(self.kb.functions.callgraph)
        total_funcs = len(sorted_funcs)

        self._update_progress(0)

        for idx, func_addr in enumerate(reversed(sorted_funcs)):
            func = self.kb.functions.get_by_addr(func_addr)

            if (func.calling_convention is None or func.prototype is None) or self._force:
                if func.alignment:
                    # skip all alignments
                    continue

                if self._skip_signature_matched_functions and func.from_signature:
                    # this function matches against a known library function. skip it.
                    continue

                if self._max_function_size is not None:
                    func_size = sum(block.size for block in func.blocks)
                    if func_size > self._max_function_size:
                        _l.info("Skipping variable recovery for %r since its size (%d) is greater than the cutoff "
                                "size (%d).", func, func_size, self._max_function_size)
                        continue

                if self._max_function_blocks is not None:
                    if len(func.block_addrs_set) > self._max_function_blocks:
                        _l.info("Skipping variable recovery for %r since its number of blocks (%d) is greater than the "
                                "cutoff number (%d).", func, len(func.block_addrs_set), self._max_function_blocks)
                        continue

                # if it's a normal function, we attempt to perform variable recovery
                if self._recover_variables and self.function_needs_variable_recovery(func):
                    _l.info("Performing variable recovery on %r...", func)
                    try:
                        _ = self.project.analyses.VariableRecoveryFast(func, kb=self.kb, low_priority=self._low_priority)
                    except claripy.ClaripyError:
                        _l.warning("An claripy exception occurred during variable recovery analysis on function %#x.",
                                   func.addr,
                                   exc_info=True,
                                   )
                        continue

                # determine the calling convention of each function
                cc_analysis = self.project.analyses.CallingConvention(func, cfg=self._cfg,
                                                                      analyze_callsites=self._analyze_callsites)
                if cc_analysis.cc is not None:
                    _l.info("Determined calling convention and prototype for %r.", func)
                    func.calling_convention = cc_analysis.cc
                    func.prototype = cc_analysis.prototype
                    func.is_prototype_guessed = True
                else:
                    _l.info("Cannot determine calling convention for %r.", func)

            percentage = (idx + 1) / total_funcs * 100.0
            self._update_progress(percentage)
            if self._low_priority:
                self._release_gil(idx, 1, 0.000001)
def _analyze ( self ) : # get an ordering of functions based on the call graph sorted_funcs = CFGUtils . quasi_topological_sort_nodes ( self . kb . functions . callgraph ) total_funcs = len ( sorted_funcs ) self . _update_progress ( 0 ) for idx , func_addr in enumerate ( reversed ( sorted_funcs ) ) : func = self . kb . functions . get_by_addr ( func_addr ) if ( func . calling_convention is None or func . prototype is None ) or self . _force : if func . alignment : # skip all alignments continue if self . _skip_signature_matched_functions and func . from_signature : # this function matches against a known library function. skip it. continue if self . _max_function_size is not None : func_size = sum ( block . size for block in func . blocks ) if func_size > self . _max_function_size : _l . info ( "Skipping variable recovery for %r since its size (%d) is greater than the cutoff " "size (%d)." , func , func_size , self . _max_function_size ) continue if self . _max_function_blocks is not None : if len ( func . block_addrs_set ) > self . _max_function_blocks : _l . info ( "Skipping variable recovery for %r since its number of blocks (%d) is greater than the " "cutoff number (%d)." , func , len ( func . block_addrs_set ) , self . _max_function_blocks ) continue # if it's a normal function, we attempt to perform variable recovery if self . _recover_variables and self . function_needs_variable_recovery ( func ) : _l . info ( "Performing variable recovery on %r..." , func ) try : _ = self . project . analyses . VariableRecoveryFast ( func , kb = self . kb , low_priority = self . _low_priority ) except claripy . ClaripyError : _l . warning ( "An claripy exception occurred during variable recovery analysis on function %#x." , func . addr , exc_info = True , ) continue # determine the calling convention of each function cc_analysis = self . project . analyses . CallingConvention ( func , cfg = self . _cfg , analyze_callsites = self . _analyze_callsites ) if cc_analysis . cc is not None : _l . info ( "Determined calling convention and prototype for %r." , func ) func . calling_convention = cc_analysis . cc func . prototype = cc_analysis . prototype func . is_prototype_guessed = True else : _l . info ( "Cannot determine calling convention for %r." , func ) percentage = ( idx + 1 ) / total_funcs * 100.0 self . _update_progress ( percentage ) if self . _low_priority : self . _release_gil ( idx , 1 , 0.000001 )