📄 sdl_dlcompat.c
字号:
if (pthread_setspecific(dlerror_key, tss)) { fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); exit(1); } } if (!tss->lockcnt) err = pthread_mutex_lock(&dlcompat_mutex); tss->lockcnt = tss->lockcnt +1; if (err) exit(err);}static inline void dounlock(void){ int err = 0; struct dlthread *tss; tss = pthread_getspecific(dlerror_key); tss->lockcnt = tss->lockcnt -1; if (!tss->lockcnt) err = pthread_mutex_unlock(&dlcompat_mutex); if (err) exit(err);}static void *SDL_OSX_dlopen(const char *path, int mode){ const struct stat *sbuf; struct dlstatus *dls; const char *fullPath; dolock(); resetdlerror(); if (!path) { dls = &mainStatus; goto dlopenok; } if (!(sbuf = findFile(path, &fullPath))) { error("file \"%s\" not found", path); goto dlopenerror; } /* Now checks that it hasn't been closed already */ if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) { /* debug("status found"); */ dls = reference(dls, mode); goto dlopenok; }#ifdef RTLD_NOLOAD if (isFlagSet(mode, RTLD_NOLOAD)) { error("no existing handle and RTLD_NOLOAD specified"); goto dlopenerror; }#endif if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) { error("how can I load something both RTLD_LAZY and RTLD_NOW?"); goto dlopenerror; } dls = loadModule(fullPath, sbuf, mode); dlopenok: dounlock(); return (void *)dls; dlopenerror: dounlock(); return NULL;}#if !FINK_BUILDstatic void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol){ int sym_len = SDL_strlen(symbol); void *value = NULL; char *malloc_sym = NULL; dolock(); malloc_sym = SDL_malloc(sym_len + 2); if (malloc_sym) { SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); value = dlsymIntern(handle, malloc_sym, 1); SDL_free(malloc_sym); } else { error("Unable to allocate memory"); goto dlsymerror; } dounlock(); return value; dlsymerror: dounlock(); return NULL;}#endif#if FINK_BUILDstatic void *dlsym_prepend_underscore(void *handle, const char *symbol){ void *answer; dolock(); answer = dlsym_prepend_underscore_intern(handle, symbol); dounlock(); return answer;}static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol){/* * A quick and easy way for porting packages which call dlsym(handle,"sym") * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then * this function will be called, and will add the required underscore. * * Note that I haven't figured out yet which should be "standard", prepend * the underscore always, or not at all. These global functions need to go away * for opendarwin. */ int sym_len = SDL_strlen(symbol); void *value = NULL; char *malloc_sym = NULL; malloc_sym = SDL_malloc(sym_len + 2); if (malloc_sym) { SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); value = dlsymIntern(handle, malloc_sym, 1); SDL_free(malloc_sym); } else { error("Unable to allocate memory"); } return value;}static void *dlsym_auto_underscore(void *handle, const char *symbol){ void *answer; dolock(); answer = dlsym_auto_underscore_intern(handle, symbol); dounlock(); return answer;}static void *dlsym_auto_underscore_intern(void *handle, const char *symbol){ struct dlstatus *dls = handle; void *addr = 0; addr = dlsymIntern(dls, symbol, 0); if (!addr) addr = dlsym_prepend_underscore_intern(handle, symbol); return addr;}static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol){ struct dlstatus *dls = handle; void *addr = 0; dolock(); addr = dlsymIntern(dls, symbol, 1); dounlock(); return addr;}#endifstatic int SDL_OSX_dlclose(void *handle){ struct dlstatus *dls = handle; dolock(); resetdlerror(); if (!isValidStatus(dls)) { goto dlcloseerror; } if (dls->module == MAGIC_DYLIB_MOD) { const char *name; if (!dls->lib) { name = "global context"; } else { name = get_lib_name(dls->lib); } warning("trying to close a .dylib!"); error("Not closing \"%s\" - dynamic libraries cannot be closed", name); goto dlcloseerror; } if (!dls->module) { error("module already closed"); goto dlcloseerror; } if (dls->refs == 1) { unsigned long options = 0; void (*fini) (void); if ((fini = dlsymIntern(dls, "__fini", 0))) { debug("calling _fini()"); fini(); } options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;#ifdef RTLD_NODELETE if (isFlagSet(dls->mode, RTLD_NODELETE)) options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;#endif if (!NSUnLinkModule(dls->module, options)) { error("unable to unlink module"); goto dlcloseerror; } dls->refs--; 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. */ } dounlock(); return 0; dlcloseerror: dounlock(); return 1;}static const char *SDL_OSX_dlerror(void){ struct dlthread *tss; const char * err_str = NULL; dlcompat_init_check(); tss = pthread_getspecific(dlerror_key); if (tss != NULL && tss->errset != 0) { tss->errset = 0; err_str = tss->errstr; } return (err_str);}/* Given an address, return the mach_header for the image containing it * or zero if the given address is not contained in any loaded images. */static const struct mach_header *image_for_address(const void *address){ unsigned long i; unsigned long j; unsigned long count = _dyld_image_count(); const struct mach_header *mh = 0; struct load_command *lc = 0; unsigned long addr = 0; for (i = 0; i < count; i++) { addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); mh = _dyld_get_image_header(i); if (mh) { lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd && addr >= ((struct segment_command *)lc)->vmaddr && addr < ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) { goto image_found; } } } mh = 0; } image_found: return mh;}#if 0 /* unused */static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info){/* FIXME: USe the routine image_for_address.*/ unsigned long i; unsigned long j; unsigned long count = _dyld_image_count(); struct mach_header *mh = 0; struct load_command *lc = 0; unsigned long addr = NULL; unsigned long table_off = (unsigned long)0; int found = 0; if (!info) return 0; dolock(); resetdlerror(); info->dli_fname = 0; info->dli_fbase = 0; info->dli_sname = 0; info->dli_saddr = 0;/* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> * to darwin-development AT lists DOT apple DOT com and slightly modified */ for (i = 0; i < count; i++) { addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); mh = _dyld_get_image_header(i); if (mh) { lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd && addr >= ((struct segment_command *)lc)->vmaddr && addr < ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) { info->dli_fname = _dyld_get_image_name(i); info->dli_fbase = (void *)mh; found = 1; break; } } if (found) break; } } if (!found) { dounlock(); return 0; } lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd) { if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) break; } } table_off = ((unsigned long)((struct segment_command *)lc)->vmaddr) - ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); debug("table off %x", table_off); lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SYMTAB == lc->cmd) { struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; struct nlist *nearest = NULL; unsigned long diff = 0xffffffff; unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); debug("symtable %x", symtable); for (i = 0; i < numsyms; i++) { /* Ignore the following kinds of Symbols */ if ((!symtable->n_value) /* Undefined */ || (symtable->n_type >= N_PEXT) /* Debug symbol */ || (!(symtable->n_type & N_EXT)) /* Local Symbol */ ) { symtable++; continue; } if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) { diff = (unsigned long)symtable->n_value - addr; nearest = symtable; } symtable++; } if (nearest) { info->dli_saddr = nearest->n_value + ((void *)p - addr); info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); } } } dounlock(); return 1;}#endif/* * Implement the dlfunc() interface, which behaves exactly the same as * dlsym() except that it returns a function pointer instead of a data * pointer. This can be used by applications to avoid compiler warnings * about undefined behavior, and is intended as prior art for future * POSIX standardization. This function requires that all pointer types * have the same representation, which is true on all platforms FreeBSD * runs on, but is not guaranteed by the C standard. */#if 0 static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol){ union { void *d; dlfunc_t f; } rv; int sym_len = SDL_strlen(symbol); char *malloc_sym = NULL; dolock(); malloc_sym = SDL_malloc(sym_len + 2); if (malloc_sym) { SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); rv.d = dlsymIntern(handle, malloc_sym, 1); SDL_free(malloc_sym); } else { error("Unable to allocate memory"); goto dlfuncerror; } dounlock(); return rv.f; dlfuncerror: dounlock(); return NULL;}#endif/* dlcompat ends, here's the SDL interface... --ryan. *//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//* System dependent library loading routines */#include "SDL_loadso.h"void *SDL_LoadObject(const char *sofile){ void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); const char *loaderror = SDL_OSX_dlerror(); if ( handle == NULL ) { SDL_SetError("Failed loading %s: %s", sofile, loaderror); } return(handle);}void *SDL_LoadFunction(void *handle, const char *name){ void *symbol = SDL_OSX_dlsym(handle, name); if ( symbol == NULL ) { SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); } return(symbol);}void SDL_UnloadObject(void *handle){ if ( handle != NULL ) { SDL_OSX_dlclose(handle); }}#endif /* SDL_LOADSO_DLCOMPAT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -