diff options
-rw-r--r-- | Python/dynload_next.c | 168 |
1 files changed, 56 insertions, 112 deletions
diff --git a/Python/dynload_next.c b/Python/dynload_next.c index 892bb47..9dec465 100644 --- a/Python/dynload_next.c +++ b/Python/dynload_next.c @@ -1,174 +1,118 @@ -/* Support for dynamic loading of extension modules */ +/* Support for dynamic loading of extension modules on Mac OS X +** All references to "NeXT" are for historical reasons. +*/ #include "Python.h" #include "importdl.h" - -#ifdef WITH_DYLD - -#define USE_DYLD - #include <mach-o/dyld.h> -#else /* WITH_DYLD */ - -#define USE_RLD -/* Define this to 1 if you want be able to load ObjC modules as well: - it switches between two different way of loading modules on the NeXT, - one that directly interfaces with the dynamic loader (rld_load(), which - does not correctly load ObjC object files), and another that uses the - ObjC runtime (objc_loadModules()) to do the job. - You'll have to add ``-ObjC'' to the compiler flags if you set this to 1. -*/ -#define HANDLE_OBJC_MODULES 1 -#if HANDLE_OBJC_MODULES -#include <objc/Object.h> -#include <objc/objc-load.h> -#endif - -#include <mach-o/rld.h> - -#endif /* WITH_DYLD */ - - const struct filedescr _PyImport_DynLoadFiletab[] = { {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, {0, 0} }; +/* +** Python modules are Mach-O MH_BUNDLE files. The best way to load these +** is each in a private namespace, so you can load, say, a module bar and a +** module foo.bar. If we load everything in the global namespace the two +** initbar() symbols will conflict. +** However, it seems some extension packages depend upon being able to access +** each others' global symbols. There seems to be no way to eat our cake and +** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour +** you get. +*/ + +#ifdef USE_DYLD_GLOBAL_NAMESPACE +#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR +#else +#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ + NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE +#endif dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) + const char *pathname, FILE *fp) { dl_funcptr p = NULL; char funcname[258]; PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname); -#ifdef USE_RLD - { - NXStream *errorStream; - struct mach_header *new_header; - const char *filenames[2]; - long ret; - unsigned long ptr; - - errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); - filenames[0] = pathname; - filenames[1] = NULL; - -#if HANDLE_OBJC_MODULES - -/* The following very bogus line of code ensures that - objc_msgSend, etc are linked into the binary. Without - it, dynamic loading of a module that includes objective-c - method calls will fail with "undefined symbol _objc_msgSend()". - This remains true even in the presence of the -ObjC flag - to the compiler -*/ - - [Object name]; - -/* objc_loadModules() dynamically loads the object files - indicated by the paths in filenames. If there are any - errors generated during loading -- typically due to the - inability to find particular symbols -- an error message - will be written to errorStream. - It returns 0 if the module is successfully loaded, 1 - otherwise. -*/ - - ret = !objc_loadModules(filenames, errorStream, - NULL, &new_header, NULL); - -#else /* !HANDLE_OBJC_MODULES */ - - ret = rld_load(errorStream, &new_header, - filenames, NULL); - -#endif /* HANDLE_OBJC_MODULES */ - - /* extract the error messages for the exception */ - if(!ret) { - char *streamBuf; - int len, maxLen; - - NXPutc(errorStream, (char)0); - - NXGetMemoryBuffer(errorStream, - &streamBuf, &len, &maxLen); - PyErr_SetString(PyExc_ImportError, streamBuf); - } - - if(ret && rld_lookup(errorStream, funcname, &ptr)) - p = (dl_funcptr) ptr; - - NXCloseMemory(errorStream, NX_FREEBUFFER); - - if(!ret) - return NULL; - } -#endif /* USE_RLD */ -#ifdef USE_DYLD - /* This is also NeXT-specific. However, frameworks (the new style - of shared library) and rld() can't be used in the same program; - instead, you have to use dyld, which is mostly unimplemented. */ { NSObjectFileImageReturnCode rc; NSObjectFileImage image; NSModule newModule; NSSymbol theSym; const char *errString; + char errBuf[512]; +#ifdef USE_DYLD_GLOBAL_NAMESPACE if (NSIsSymbolNameDefined(funcname)) { theSym = NSLookupAndBindSymbol(funcname); p = (dl_funcptr)NSAddressOfSymbol(theSym); return p; } +#endif rc = NSCreateObjectFileImageFromFile(pathname, &image); switch(rc) { - default: - case NSObjectFileImageFailure: - case NSObjectFileImageFormat: - /* for these a message is printed on stderr by dyld */ + default: + case NSObjectFileImageFailure: + case NSObjectFileImageFormat: + /* for these a message is printed on stderr by dyld */ errString = "Can't create object file image"; break; - case NSObjectFileImageSuccess: + case NSObjectFileImageSuccess: errString = NULL; break; - case NSObjectFileImageInappropriateFile: + case NSObjectFileImageInappropriateFile: errString = "Inappropriate file type for dynamic loading"; break; - case NSObjectFileImageArch: + case NSObjectFileImageArch: errString = "Wrong CPU type in object file"; break; - case NSObjectFileImageAccess: + case NSObjectFileImageAccess: errString = "Can't read object file (no access)"; break; } if (errString == NULL) { - newModule = NSLinkModule(image, pathname, - NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR); - if (!newModule) - errString = "Failure linking new module"; + newModule = NSLinkModule(image, pathname, LINKOPTIONS); + if (newModule == NULL) { + int errNo; + char *fileName, *moreErrorStr; + NSLinkEditErrors c; + NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); + PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", + fileName, moreErrorStr); + errString = errBuf; + } } if (errString != NULL) { PyErr_SetString(PyExc_ImportError, errString); return NULL; } +#ifdef USE_DYLD_GLOBAL_NAMESPACE if (!NSIsSymbolNameDefined(funcname)) { /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ NSUnLinkModule(newModule, FALSE); PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); + "Loaded module does not contain symbol %.200s", + funcname); return NULL; } theSym = NSLookupAndBindSymbol(funcname); +#else + theSym = NSLookupSymbolInModule(newModule, funcname); + if ( theSym == NULL ) { + NSUnLinkModule(newModule, FALSE); + PyErr_Format(PyExc_ImportError, + "Loaded module does not contain symbol %.200s", + funcname); + return NULL; + } +#endif p = (dl_funcptr)NSAddressOfSymbol(theSym); - } -#endif /* USE_DYLD */ + } return p; } |