1 
2 /* Support for dynamic loading of extension modules on Mac OS X
3 ** All references to "NeXT" are for historical reasons.
4 */
5 
6 #include "Python.h"
7 #include "importdl.h"
8 
9 #include <mach-o/dyld.h>
10 
11 const struct filedescr _PyImport_DynLoadFiletab[] = {
12     {".so", "rb", C_EXTENSION},
13     {"module.so", "rb", C_EXTENSION},
14     {0, 0}
15 };
16 
17 /*
18 ** Python modules are Mach-O MH_BUNDLE files. The best way to load these
19 ** is each in a private namespace, so you can load, say, a module bar and a
20 ** module foo.bar. If we load everything in the global namespace the two
21 ** initbar() symbols will conflict.
22 ** However, it seems some extension packages depend upon being able to access
23 ** each others' global symbols. There seems to be no way to eat our cake and
24 ** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour
25 ** you get.
26 */
27 
28 #ifdef USE_DYLD_GLOBAL_NAMESPACE
29 #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR
30 #else
31 #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
32     NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
33 #endif
_PyImport_GetDynLoadFunc(const char * fqname,const char * shortname,const char * pathname,FILE * fp)34 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
35                                         const char *pathname, FILE *fp)
36 {
37     dl_funcptr p = NULL;
38     char funcname[258];
39     NSObjectFileImageReturnCode rc;
40     NSObjectFileImage image;
41     NSModule newModule;
42     NSSymbol theSym;
43     const char *errString;
44     char errBuf[512];
45 
46     PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
47 
48 #ifdef USE_DYLD_GLOBAL_NAMESPACE
49     if (NSIsSymbolNameDefined(funcname)) {
50         theSym = NSLookupAndBindSymbol(funcname);
51         p = (dl_funcptr)NSAddressOfSymbol(theSym);
52         return p;
53     }
54 #endif
55     rc = NSCreateObjectFileImageFromFile(pathname, &image);
56     switch(rc) {
57         default:
58         case NSObjectFileImageFailure:
59         case NSObjectFileImageFormat:
60             /* for these a message is printed on stderr by dyld */
61             errString = "Can't create object file image";
62         break;
63         case NSObjectFileImageSuccess:
64             errString = NULL;
65             break;
66         case NSObjectFileImageInappropriateFile:
67             errString = "Inappropriate file type for dynamic loading";
68             break;
69         case NSObjectFileImageArch:
70             errString = "Wrong CPU type in object file";
71             break;
72         case NSObjectFileImageAccess:
73             errString = "Can't read object file (no access)";
74             break;
75     }
76     if (errString == NULL) {
77         newModule = NSLinkModule(image, pathname, LINKOPTIONS);
78         if (newModule == NULL) {
79             int errNo;
80             const char *fileName, *moreErrorStr;
81             NSLinkEditErrors c;
82             NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
83             PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
84                             fileName, moreErrorStr);
85             errString = errBuf;
86         }
87     }
88     if (errString != NULL) {
89         PyErr_SetString(PyExc_ImportError, errString);
90         return NULL;
91     }
92 #ifdef USE_DYLD_GLOBAL_NAMESPACE
93     if (!NSIsSymbolNameDefined(funcname)) {
94         /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
95         /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
96         PyErr_Format(PyExc_ImportError,
97                          "Loaded module does not contain symbol %.200s",
98                          funcname);
99         return NULL;
100     }
101     theSym = NSLookupAndBindSymbol(funcname);
102 #else
103     theSym = NSLookupSymbolInModule(newModule, funcname);
104     if ( theSym == NULL ) {
105         /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
106         PyErr_Format(PyExc_ImportError,
107                          "Loaded module does not contain symbol %.200s",
108                          funcname);
109         return NULL;
110     }
111 #endif
112     p = (dl_funcptr)NSAddressOfSymbol(theSym);
113     return p;
114 }
115