'Hook a section of code with a custom function. This is used internally to provide symbolic
summaries of library functions, and can be used to instrument execution or to modify
control flow.
When hook is not specified, it returns a function decorator that allows easy hooking.
Usage::
# Assuming proj is an instance of angr.Project, we will add a custom hook at the entry
# point of the project.
@proj.hook(proj.entry)
def my_hook(state):
print "Welcome to execution!"
:param addr:        The address to hook.
:param hook:        A :class:`angr.project.Hook` describing a procedure to run at the
given address. You may also pass in a SimProcedure class or a function
directly and it will be wrapped in a Hook object for you.
:param length:      If you provide a function for the hook, this is the number of bytes
that will be skipped by executing the hook by default.
:param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
arguments that will be passed to the procedure\'s `run` method
eventually.'

def hook(self, addr, hook=None, length=0, kwargs=None):

    if (hook is None):
        return self._hook_decorator(addr, length=length, kwargs=kwargs)
    if (kwargs is None):
        kwargs = {}
    l.debug('hooking    %#x    with    %s', addr, hook)
    if self.is_hooked(addr):
        l.warning('Address    is    already    hooked    [hook(%#x,    %s)].    Not    re-hooking.', addr, hook)
        return
    if isinstance(hook, type):
        if once('hook_instance_warning'):
            l.critical('Hooking    with    a    SimProcedure    instance    is    deprecated!    Please    hook    with    an    instance.')
        hook = hook(**kwargs)
    if callable(hook):
        hook = SIM_PROCEDURES['stubs']['UserHook'](user_func=hook, length=length, **kwargs)
    self._sim_procedures[addr] = hook
