(self, variables: List, var_manager)
return args.difference(restored_reg_vars)
Derive function arguments from input variables.

        :param variables:
        :param var_manager: The variable manager of this function.
        :return:
Derive function arguments from input variables.
Derive function arguments from input variables .
def _args_from_vars(self, variables: List, var_manager):
        """
        Derive function arguments from input variables.

        :param variables:
        :param var_manager: The variable manager of this function.
        :return:
        """

        args = set()
        if not self.project.arch.call_pushes_ret:
            ret_addr_offset = 0
        else:
            ret_addr_offset = self.project.arch.bytes

        reg_vars_with_single_access: List[SimRegisterVariable] = []

        for variable in variables:
            if isinstance(variable, SimStackVariable):
                # a stack variable. convert it to a stack argument.
                # TODO: deal with the variable base
                if variable.offset <= 0:
                    # skip the return address on the stack
                    # TODO: make sure it was the return address
                    continue
                arg = SimStackArg(variable.offset - ret_addr_offset, variable.size)
                args.add(arg)
            elif isinstance(variable, SimRegisterVariable):
                # a register variable, convert it to a register argument
                if not self._is_sane_register_variable(variable):
                    continue
                reg_name = self.project.arch.translate_register_name(variable.reg, size=variable.size)
                arg = SimRegArg(reg_name, variable.size)
                args.add(arg)

                accesses = var_manager.get_variable_accesses(variable)
                if len(accesses) == 1:
                    reg_vars_with_single_access.append(variable)
            else:
                l.error('Unsupported type of variable %s.', type(variable))

        # the function might be saving registers at the beginning and restoring them at the end
        # we should remove all registers that are strictly callee-saved and are not used anywhere in this function
        end_blocks = [ (endpoint.addr, endpoint.size) for endpoint in self._function.endpoints_with_type['return'] ]

        restored_reg_vars: Set[SimRegArg] = set()

        # is there any instruction that restores this register in any end blocks?
        if reg_vars_with_single_access:
            if self._function.returning is False:
                # no restoring is required if this function does not return
                for var_ in reg_vars_with_single_access:
                    reg_name = self.project.arch.translate_register_name(var_.reg, size=var_.size)
                    restored_reg_vars.add(SimRegArg(reg_name, var_.size))

            else:
                reg_offsets: Set[int] = set(r.reg for r in reg_vars_with_single_access)
                for var_ in var_manager.get_variables(sort="reg"):
                    if var_.reg in reg_offsets:
                        # check if there is only a write to it
                        accesses = var_manager.get_variable_accesses(var_)
                        if len(accesses) == 1 and accesses[0].access_type == VariableAccessSort.WRITE:
                            found = False
                            for end_block_addr, end_block_size in end_blocks:
                                if end_block_addr <= accesses[0].location.ins_addr < end_block_addr + end_block_size:
                                    found = True
                                    break

                            if found:
                                reg_name = self.project.arch.translate_register_name(var_.reg, size=var_.size)
                                restored_reg_vars.add(SimRegArg(reg_name, var_.size))

        return args.difference(restored_reg_vars)
def _args_from_vars ( self , variables : List , var_manager ) : args = set ( ) if not self . project . arch . call_pushes_ret : ret_addr_offset = 0 else : ret_addr_offset = self . project . arch . bytes reg_vars_with_single_access : List [ SimRegisterVariable ] = [ ] for variable in variables : if isinstance ( variable , SimStackVariable ) : # a stack variable. convert it to a stack argument. # TODO: deal with the variable base if variable . offset <= 0 : # skip the return address on the stack # TODO: make sure it was the return address continue arg = SimStackArg ( variable . offset - ret_addr_offset , variable . size ) args . add ( arg ) elif isinstance ( variable , SimRegisterVariable ) : # a register variable, convert it to a register argument if not self . _is_sane_register_variable ( variable ) : continue reg_name = self . project . arch . translate_register_name ( variable . reg , size = variable . size ) arg = SimRegArg ( reg_name , variable . size ) args . add ( arg ) accesses = var_manager . get_variable_accesses ( variable ) if len ( accesses ) == 1 : reg_vars_with_single_access . append ( variable ) else : l . error ( 'Unsupported type of variable %s.' , type ( variable ) ) # the function might be saving registers at the beginning and restoring them at the end # we should remove all registers that are strictly callee-saved and are not used anywhere in this function end_blocks = [ ( endpoint . addr , endpoint . size ) for endpoint in self . _function . endpoints_with_type [ 'return' ] ] restored_reg_vars : Set [ SimRegArg ] = set ( ) # is there any instruction that restores this register in any end blocks? if reg_vars_with_single_access : if self . _function . returning is False : # no restoring is required if this function does not return for var_ in reg_vars_with_single_access : reg_name = self . project . arch . translate_register_name ( var_ . reg , size = var_ . size ) restored_reg_vars . add ( SimRegArg ( reg_name , var_ . size ) ) else : reg_offsets : Set [ int ] = set ( r . reg for r in reg_vars_with_single_access ) for var_ in var_manager . get_variables ( sort = "reg" ) : if var_ . reg in reg_offsets : # check if there is only a write to it accesses = var_manager . get_variable_accesses ( var_ ) if len ( accesses ) == 1 and accesses [ 0 ] . access_type == VariableAccessSort . WRITE : found = False for end_block_addr , end_block_size in end_blocks : if end_block_addr <= accesses [ 0 ] . location . ins_addr < end_block_addr + end_block_size : found = True break if found : reg_name = self . project . arch . translate_register_name ( var_ . reg , size = var_ . size ) restored_reg_vars . add ( SimRegArg ( reg_name , var_ . size ) ) return args . difference ( restored_reg_vars )