Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        Additionally, if instead of a symbol name you provide an address, some secret functionality will
        kick in and you will probably just hook that address, UNLESS you're on powerpc64 ABIv1 or some
        yet-unknown scary ABI that has its function pointers point to something other than the actual
        functions, in which case it'll do the right thing.

        :param symbol_name: The name of the dependency to resolve.
        :param simproc:     The SimProcedure instance (or function) with which to hook the symbol
        :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.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int

def hook_symbol(self, symbol_name, simproc, kwargs=None, replace=None):
        """
        Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        Additionally, if instead of a symbol name you provide an address, some secret functionality will
        kick in and you will probably just hook that address, UNLESS you're on powerpc64 ABIv1 or some
        yet-unknown scary ABI that has its function pointers point to something other than the actual
        functions, in which case it'll do the right thing.

        :param symbol_name: The name of the dependency to resolve.
        :param simproc:     The SimProcedure instance (or function) with which to hook the symbol
        :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.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(symbol_name) is not int:
            sym = self.loader.find_symbol(symbol_name)
            if sym is None:
                # it could be a previously unresolved weak symbol..?
                new_sym = None
                for reloc in self.loader.find_relevant_relocations(symbol_name):
                    if not reloc.symbol.is_weak:
                        raise Exception("Symbol is strong but we couldn't find its resolution? Report to @rhelmot.")
                    if new_sym is None:
                        new_sym = self.loader.extern_object.make_extern(symbol_name)
                    reloc.resolve(new_sym)
                    reloc.relocate([])

                if new_sym is None:
                    l.error("Could not find symbol %s", symbol_name)
                    return None
                sym = new_sym

            basic_addr = sym.rebased_addr
        else:
            basic_addr = symbol_name
            symbol_name = None

        hook_addr, _ = self.simos.prepare_function_symbol(symbol_name, basic_addr=basic_addr)

        self.hook(hook_addr, simproc, kwargs=kwargs, replace=replace)
        return hook_addr