<commit_before>import logging
import networkx
import string
from collections import defaultdict

import simuvex
import simuvex.s_cc
import claripy

l = logging.getLogger(name="angr.knowledge.function")


class Function(object):
    """
    A representation of a function and various information about it.
    """
    def __init__(self, function_manager, addr, name=None, syscall=False):
        """
        Function constructor

        :param addr:            The address of the function.
        :param name:            (Optional) The name of the function.
        :param syscall:         (Optional) Whether this function is a syscall or not.
        """
        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 (basic block nodes) at whose ends the function terminates
        # in theory, if everything works fine, endpoints == ret_sites | jumpout_sites | callout_sites
        self._endpoints = set()

        self._call_sites = {}
        self.addr = addr
        self._function_manager = function_manager
        self.is_syscall = syscall

        self._project = project = self._function_manager._kb._project

        self.is_plt = False
        self.is_simprocedure = False

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

        if project.loader.find_plt_stub_name(addr) is not None:
            # Whether this function is a plt entry or not is fully relying on the PLT detection in CLE
            self.is_plt = True

        # Try to get a name from existing labels
        if name is None and addr in function_manager._kb.labels:
            name = function_manager._kb.labels[addr]

        # try to get the name from a hook
        if name is None:
            if project.is_hooked(addr):
                hooker = project.hooked_by(addr)
                if hooker is simuvex.SimProcedures['stubs']['ReturnUnconstrained']:
                    kwargs_dict = project._sim_procedures[addr][1]
                    if 'resolves' in kwargs_dict:
                        name = kwargs_dict['resolves']
                else:
                    name = hooker.__name__.split('.')[-1]

        # try to get the name from the symbols
        if name is None:
            so = project.loader.addr_belongs_to_object(addr)
            print so, addr
            if so is not None and addr in so.symbols_by_addr:
                name = so.symbols_by_addr[addr].name
                print name

        # generate an IDA-style sub_X name
        if name is None:
            name = 'sub_%x' % addr

        self._name = None
        self.name = name

        # Register offsets of those arguments passed in registers
        self._argument_registers = []
        # Stack offsets of those arguments passed in stack variables
        self._argument_stack_variables = []

        # These properties are set by VariableManager
        self.bp_on_stack = False<commit_msg>disable this, since the labels take care of it<commit_after>import logging
import networkx
import string
from collections import defaultdict

import simuvex
import simuvex.s_cc
import claripy

l = logging.getLogger(name="angr.knowledge.function")


class Function(object):
    """
    A representation of a function and various information about it.
    """
    def __init__(self, function_manager, addr, name=None, syscall=False):
        """
        Function constructor

        :param addr:            The address of the function.
        :param name:            (Optional) The name of the function.
        :param syscall:         (Optional) Whether this function is a syscall or not.
        """
        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 (basic block nodes) at whose ends the function terminates
        # in theory, if everything works fine, endpoints == ret_sites | jumpout_sites | callout_sites
        self._endpoints = set()

        self._call_sites = {}
        self.addr = addr
        self._function_manager = function_manager
        self.is_syscall = syscall

        self._project = project = self._function_manager._kb._project

        self.is_plt = False
        self.is_simprocedure = False

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

        if project.loader.find_plt_stub_name(addr) is not None:
            # Whether this function is a plt entry or not is fully relying on the PLT detection in CLE
            self.is_plt = True

        # Try to get a name from existing labels
        if name is None and addr in function_manager._kb.labels:
            name = function_manager._kb.labels[addr]

        # try to get the name from a hook
        if name is None:
            if project.is_hooked(addr):
                hooker = project.hooked_by(addr)
                if hooker is simuvex.SimProcedures['stubs']['ReturnUnconstrained']:
                    kwargs_dict = project._sim_procedures[addr][1]
                    if 'resolves' in kwargs_dict:
                        name = kwargs_dict['resolves']
                else:
                    name = hooker.__name__.split('.')[-1]

        # try to get the name from the symbols
        #if name is None:
        #   so = project.loader.addr_belongs_to_object(addr)
        #   if so is not None and addr in so.symbols_by_addr:
        #       name = so.symbols_by_addr[addr].name
        #       print name

        # generate an IDA-style sub_X name
        if name is None:
            name = 'sub_%x' % addr

        self._name = None
        self.name = name

        # Register offsets of those arguments passed in registers
        self._argument_registers = []
        # Stack offsets of those arguments passed in stack variables
        self._argument_stack_variables = []

        # These properties are set by VariableManager
        self.bp_on_stack = False
{'fraction_non_alphanumeric': 0.06688612898398923, 'fraction_numerical': 0.0005985335926978902, 'mean_word_length': 2.085872576177285, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5540045', 'n_tokens_mistral': 1809, 'n_tokens_neox': 1706, 'n_words': 602}