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; }
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; }
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); }