示例#1
0
int dlclose(void * handle)
{
    struct dlstatus * dls = handle;
    if (!isValidStatus(dls))
        return 1;
    if (dls->module == MAGIC_DYLIB_MOD)
    {
        warning("trying to close a .dylib!");
        error("dynamic libraries cannot be closed");
        // Code inside the PAL expects to be able to dlclose anything that
        // could be dlopen'd, so we return success here. It doesn't matter
        // that we don't do anything; the PAL doesn't require any action
        // as a result of this dlclose. Clients of the PAL can't call
        // dlclose() directly, so this isn't a concern.
        return 0;
    }
    if (!dls->module)
    {
        error("module already closed");
        return 1;
    }
    dls->refs--;
    if (!dls->refs)
    {
        unsigned long options = 0;
        void (*fini)(void);
        if ((fini = dlsymIntern(dls, "__fini",0)))
        {
            debug("calling _fini()");
            fini();
        }
        if (isFlagSet(dls->mode, RTLD_NODELETE))
            options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
        if (!NSUnLinkModule(dls->module, options))
        {
            error("unable to unlink module");
            return 1;
        }
        dls->module = 0;
        /* Note: the dlstatus struct dls is neither removed from the list
         * nor is the memory it occupies freed. This shouldn't pose a 
         * problem in mostly all cases, though.
         */
    }
    return 0;
}
示例#2
0
void *dlsym(void * handle, const char *symbol)
{
    struct dlstatus * dls = handle;
    char *mangledSymbol;
    void *addr = 0;

    if (!isValidStatus(dls))
        return NULL;

    // We need to "mangle" the symbol name because dyld only deals
    // with symbol names as the linker constructs them. The linker
    // adds a leading underscore.
    mangledSymbol = alloca(strlen(symbol) + 2);
    mangledSymbol[0] = '_';
    mangledSymbol[1] = '\0';
    strcat(mangledSymbol, symbol);

    addr = dlsymIntern(dls, mangledSymbol, 1);
    return addr;
}
示例#3
0
static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError)
{
	NSSymbol *nssym = 0;
#ifdef __GCC__
	void *caller = __builtin_return_address(1);	/* Be *very* careful about inlining */
#else
        void *caller = NULL;
#endif
	const struct mach_header *caller_mh = 0;
	const char* savedErrorStr = NULL;
	resetdlerror();
#ifndef RTLD_SELF
#define	RTLD_SELF		((void *) -3)
#endif
	if (NULL == dls)
		dls = RTLD_SELF;
	if ((RTLD_NEXT == dls) || (RTLD_SELF == dls))
	{
		if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
		{
			caller_mh = image_for_address(caller);
			if (RTLD_SELF == dls)
			{
				/* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
				 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c
				 * this is acceptable.
				 */
				if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
				{
					nssym = dyld_NSLookupSymbolInImage(caller_mh,
													   symbol,
													   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
													   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
				}
			}
			if (!nssym)
			{
				if (RTLD_SELF == dls)
					savedErrorStr = dyld_error_str();
				nssym = search_linked_libs(caller_mh, symbol);
			}
		}
		else
		{
			if (canSetError)
				error("RTLD_SELF and RTLD_NEXT are not supported");
			return NULL;
		}
	}
	if (!nssym)
	{

		if (RTLD_DEFAULT == dls)
		{
			dls = &mainStatus;
		}
		if (!isValidStatus(dls))
			return NULL;

		if (dls->module != MAGIC_DYLIB_MOD)
		{
			nssym = NSLookupSymbolInModule(dls->module, symbol);
			if (!nssym && NSIsSymbolNameDefined(symbol))
			{
				debug("Searching dependencies");
				savedErrorStr = dyld_error_str();
				nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol);
			}
		}
		else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
		{
			if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol))
			{
				nssym = dyld_NSLookupSymbolInImage(dls->lib,
												   symbol,
												   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
												   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
			}
			else if (NSIsSymbolNameDefined(symbol))
			{
				debug("Searching dependencies");
				savedErrorStr = dyld_error_str();
				nssym = search_linked_libs(dls->lib, symbol);
			}
		}
		else if (dls->module == MAGIC_DYLIB_MOD)
		{
			/* Global context, use NSLookupAndBindSymbol */
			if (NSIsSymbolNameDefined(symbol))
			{
				/* There doesn't seem to be a return on error option for this call???
				   this is potentially broken, if binding fails, it will improperly
				   exit the application. */
				nssym = NSLookupAndBindSymbol(symbol);
			}
			else
			{
				if (savedErrorStr)
					free((char*)savedErrorStr);			
				savedErrorStr = malloc(256);
				snprintf((char*)savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol);	
			}
		}
	}
	/* Error reporting */
	if (!nssym)
	{
		if (!savedErrorStr || !strlen(savedErrorStr))
		{
			if (savedErrorStr)
				free((char*)savedErrorStr);
			savedErrorStr = malloc(256);
			snprintf((char*)savedErrorStr, 256,"Symbol \"%s\" not found",symbol);
		}
		if (canSetError)
		{
			error(savedErrorStr);
		}
		else
		{
			debug(savedErrorStr);
		}
		if (savedErrorStr)
			free((char*)savedErrorStr);
		return NULL;
	}
	return NSAddressOfSymbol(nssym);
}