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