X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fsysdll.c;h=c9e28c04d1dae4c55d10f2ed2831a283a1e1a83f;hb=515ed47192a2fc212474dc246a875771890e0cbe;hp=35e9117da892e3c5b4a53bc7d4b82e2ea1e6c414;hpb=762383636a99307282c2d93d26c35c046ec24da1;p=chise%2Fxemacs-chise.git.1 diff --git a/src/sysdll.c b/src/sysdll.c index 35e9117..c9e28c0 100644 --- a/src/sysdll.c +++ b/src/sysdll.c @@ -24,28 +24,24 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #endif #include +#include "lisp.h" #include "sysdll.h" /* This whole file is conditional upon HAVE_SHLIB */ #ifdef HAVE_SHLIB /* Thankfully, most systems follow the ELFish dlopen() method. -** HAVE__DLOPEN is lame, but SCO has their dl* functions as _dl*, and -** unless you include dlfcn.h you don't get the macros to mask them, and -** autoconf fails to find them. No longer true as of 5.0.5. -** -** Anybody who wants to use this on SCO needs to have their configure.in -** look for _dlopen() as well as dlopen() */ -#if defined(HAVE_DLOPEN) || defined(HAVE__DLOPEN) || defined(HAVE_DLFCN_H) + +#if defined(HAVE_DLOPEN) #include #ifndef RTLD_LAZY # define RTLD_LAZY 1 #endif /* RTLD_LAZY isn't defined under FreeBSD - ick */ -#ifndef RTLD_GLOBAL -# define RTLD_GLOBAL 0 +#ifndef RTLD_NOW +# define RTLD_NOW 2 #endif int @@ -54,16 +50,17 @@ dll_init (const char *arg) return 0; } + dll_handle dll_open (const char *fname) { - return (dll_handle)dlopen (fname, RTLD_LAZY | RTLD_GLOBAL); + return (dll_handle) dlopen (fname, RTLD_NOW); } int dll_close (dll_handle h) { - return dlclose((void *)h); + return dlclose ((void *) h); } dll_func @@ -72,10 +69,10 @@ dll_function (dll_handle h, const char *n) #ifdef DLSYM_NEEDS_UNDERSCORE char *buf = alloca_array (char, strlen (n) + 2); *buf = '_'; - (void)strcpy(buf + 1, n); + strcpy (buf + 1, n); n = buf; #endif - return (dll_func)dlsym ((void *)h, n); + return (dll_func) dlsym ((void *) h, n); } dll_var @@ -84,7 +81,7 @@ dll_variable (dll_handle h, const char *n) #ifdef DLSYM_NEEDS_UNDERSCORE char *buf = alloca_array (char, strlen (n) + 2); *buf = '_'; - (void)strcpy(buf + 1, n); + strcpy (buf + 1, n); n = buf; #endif return (dll_var)dlsym ((void *)h, n); @@ -94,9 +91,9 @@ const char * dll_error (dll_handle h) { #if defined(HAVE_DLERROR) || defined(dlerror) - return (const char *)dlerror (); + return (const char *) dlerror (); #elif defined(HAVE__DLERROR) - return (const char *)_dlerror(); + return (const char *) _dlerror(); #else return "Shared library error"; #endif @@ -114,26 +111,16 @@ dll_init (const char *arg) dll_handle dll_open (const char *fname) { - shl_t h = shl_load (fname, BIND_DEFERRED,0L); - shl_t *hp = NULL; + /* shl_load will hang hard if passed a NULL fname. */ + if (fname == NULL) return NULL; - if (h) - { - hp = (shl_t *)malloc (sizeof (shl_t)); - if (!hp) - shl_unload(h); - else - *hp = h; - } - return (dll_handle)hp; + return (dll_handle) shl_load (fname, BIND_DEFERRED,0L); } int dll_close (dll_handle h) { - shl_t hp = *((shl_t *)h); - free (hp); - return shl_unload(h); + return shl_unload ((shl_t) h); } dll_func @@ -141,10 +128,10 @@ dll_function (dll_handle h, const char *n) { long handle = 0L; - if (shl_findsym ((shl_t *)h, n, TYPE_PROCEDURE, &handle)) + if (shl_findsym ((shl_t *) &h, n, TYPE_PROCEDURE, &handle)) return NULL; - return (dll_func)handle; + return (dll_func) handle; } dll_var @@ -152,10 +139,10 @@ dll_variable (dll_handle h, const char *n) { long handle = 0L; - if (shl_findsym ((shl_t *)h, n, TYPE_DATA, &handle)) + if (shl_findsym ((shl_t *) &h, n, TYPE_DATA, &handle)) return NULL; - return (dll_var)handle; + return (dll_var) handle; } const char * @@ -166,7 +153,7 @@ dll_error (dll_handle h) return "Generic shared library error"; } -#elif defined(HAVE_INIT_DLD) +#elif defined(HAVE_DLD_INIT) #include int dll_init (const char *arg) @@ -190,7 +177,7 @@ dll_open (const char *fname) if (rc) return NULL; - return (dll_handle)1; + return (dll_handle) 1; } int @@ -208,13 +195,13 @@ dll_close (dll_handle h) DLL_FUNC dll_function (dll_handle h, const char *n) { - return dld_get_func(n); + return dld_get_func (n); } DLL_FUNC dll_variable (dll_handle h, const char *n) { - return dld_get_symbol(n); + return dld_get_symbol (n); } #elif defined (WIN32_NATIVE) @@ -231,7 +218,7 @@ dll_init (const char *arg) dll_handle dll_open (const char *fname) { - return (dll_handle)LoadLibrary (fname); + return (dll_handle) LoadLibrary (fname); } int @@ -243,13 +230,13 @@ dll_close (dll_handle h) dll_func dll_function (dll_handle h, const char *n) { - return (dll_func)GetProcAddress (h,n); + return (dll_func) GetProcAddress (h, n); } dll_func dll_variable (dll_handle h, const char *n) { - return (dll_func)GetProcAddress (h,n); + return (dll_func) GetProcAddress (h, n); } const char * @@ -257,8 +244,242 @@ dll_error (dll_handle h) { return "Windows DLL Error"; } +#elif defined(HAVE_DYLD) + +/* + This section supports MacOSX dynamic libraries. Dynamically + loadable libraries must be compiled as bundles, not dynamiclibs. +*/ + +#include + +int +dll_init (const char *arg) +{ + return 0; +} + +dll_handle +dll_open (const char *fname) +{ + NSObjectFileImage file; + NSObjectFileImageReturnCode ret; + + /* + * MacOS X dll support is for bundles, not the current executable, so return + * NULL is this case. However, dll_function() uses a special hack where a + * NULL handle can be used to find executable symbols. This satisfies the + * needs of ui-gtk.c but is not a general solution. + */ + if (fname == NULL) + return NULL; + + ret = NSCreateObjectFileImageFromFile(fname, &file); + + if (ret != NSObjectFileImageSuccess) { + return NULL; + } + + return (dll_handle)NSLinkModule(file, fname, + NSLINKMODULE_OPTION_BINDNOW | + NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); +} + +int +dll_close (dll_handle h) +{ + return NSUnLinkModule((NSModule)h, NSUNLINKMODULE_OPTION_NONE); +} + +/* 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. + * + * Note: image_for_address(), my_find_image() and search_linked_libs() are + * based on code from the dlcompat library + * (http://www.opendarwin.org/projects/dlcompat). + */ + +static struct mach_header* +image_for_address(void *address) +{ + unsigned long i; + unsigned long count = _dyld_image_count(); + struct mach_header *mh = 0; + + for (i = 0; i < count; i++) + { + unsigned long addr = (unsigned long)address - + _dyld_get_image_vmaddr_slide(i); + mh = _dyld_get_image_header(i); + + if (mh) + { + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + unsigned long j; + + 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; +} + +static const struct mach_header* +my_find_image(const char *name) +{ + const struct mach_header *mh = (struct mach_header *) + NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + + if (!mh) + { + int count = _dyld_image_count(); + int j; + + for (j = 0; j < count; j++) + { + const char *id = _dyld_get_image_name(j); + + if (!strcmp(id, name)) + { + mh = _dyld_get_image_header(j); + break; + } + } + } + + return mh; +} + +/* + * dyld adds libraries by first adding the directly dependant libraries in + * link order, and then adding the dependencies for those libraries, so we + * should do the same... but we don't bother adding the extra dependencies, if + * the symbols are neither in the loaded image nor any of it's direct + * dependencies, then it probably isn't there. + */ +static NSSymbol +search_linked_libs(const struct mach_header * mh, const char *symbol) +{ + int n; + NSSymbol nssym = 0; + + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + + for (n = 0; n < mh->ncmds; + n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + struct mach_header *wh; + + if ((wh = (struct mach_header *) + my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + + (char *)lc)))) + { + if (NSIsSymbolNameDefinedInImage(wh, symbol)) + { + nssym = + NSLookupSymbolInImage(wh, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + break; + } + } + } + } + + return nssym; +} + +dll_func +dll_function (dll_handle h, const char *n) +{ + NSSymbol sym = 0; +#ifdef DLSYM_NEEDS_UNDERSCORE + char *buf = alloca_array (char, strlen (n) + 2); + *buf = '_'; + strcpy (buf + 1, n); + n = buf; +#endif + + /* NULL means the program image and shared libraries, not bundles. */ + + if (h == NULL) + { + /* NOTE: This assumes that this function is included in the main program + and not in a shared library. */ + const struct mach_header* my_mh = image_for_address(&dll_function); + + if (NSIsSymbolNameDefinedInImage(my_mh, n)) + { + sym = + NSLookupSymbolInImage(my_mh, + n, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + + if (!sym) + { + sym = search_linked_libs(my_mh, n); + } + } + else + { + sym = NSLookupSymbolInModule((NSModule)h, n); + } + + if (sym == 0) return 0; + return (dll_func)NSAddressOfSymbol(sym); +} + +dll_var +dll_variable (dll_handle h, const char *n) +{ + NSSymbol sym; +#ifdef DLSYM_NEEDS_UNDERSCORE + char *buf = alloca_array (char, strlen (n) + 2); + *buf = '_'; + strcpy (buf + 1, n); + n = buf; +#endif + sym = NSLookupSymbolInModule((NSModule)h, n); + if (sym == 0) return 0; + return (dll_var)NSAddressOfSymbol(sym); +} + +const char * +dll_error (dll_handle h) +{ + NSLinkEditErrors c; + int errorNumber; + const char *fileNameWithError, *errorString; + NSLinkEditError(&c, &errorNumber, &fileNameWithError, &errorString); + return errorString; +} + + #else -/* Catchall if we don't know about this systems method of dynamic loading */ +/* Catchall if we don't know about this system's method of dynamic loading */ int dll_init (const char *arg) {