summaryrefslogtreecommitdiffstats
path: root/Python/dynload_next.c
blob: 9dec4656987b002b6155dfcad042bf4d75696e20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

/* 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"

#include <mach-o/dyld.h>

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)
{
	dl_funcptr p = NULL;
	char funcname[258];

	PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);

	{
		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 */
			errString = "Can't create object file image";
			break;
			case NSObjectFileImageSuccess:
			errString = NULL;
			break;
			case NSObjectFileImageInappropriateFile:
			errString = "Inappropriate file type for dynamic loading";
			break;
			case NSObjectFileImageArch:
			errString = "Wrong CPU type in object file";
			break;
			case NSObjectFileImageAccess:
			errString = "Can't read object file (no access)";
			break;
		}
		if (errString == NULL) {
			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);
			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);
	}

	return p;
}