blob: 75544ed3bc38222e8fafa340ae35e7a2b4f90b86 [file] [log] [blame]
Guido van Rossum22a1d361999-12-20 21:18:49 +00001
2/* Support for dynamic loading of extension modules */
3
4#include "Python.h"
5#include "importdl.h"
6
7#include <sys/types.h>
8#include <sys/stat.h>
Martin v. Löwis8a57f002001-10-18 21:24:04 +00009
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000010#if defined(__NetBSD__)
11#include <sys/param.h>
12#if (NetBSD < 199712)
Guido van Rossum22a1d361999-12-20 21:18:49 +000013#include <nlist.h>
14#include <link.h>
15#define dlerror() "error in dynamic linking"
Martin v. Löwis8a57f002001-10-18 21:24:04 +000016#endif
17#endif /* NetBSD */
18
Guido van Rossum22a1d361999-12-20 21:18:49 +000019#ifdef HAVE_DLFCN_H
20#include <dlfcn.h>
Andrew MacIntyred9400542002-02-26 11:41:34 +000021#else
22#if defined(PYOS_OS2) && defined(PYCC_GCC)
23#include "dlfcn.h"
24#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000025#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000026
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000027#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
Guido van Rossumc8fcdcb2000-10-25 22:07:45 +000028#define LEAD_UNDERSCORE "_"
29#else
30#define LEAD_UNDERSCORE ""
31#endif
32
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000033/* The .so extension module ABI tag, supplied by the Makefile via
34 Makefile.pre.in and configure. This is used to discriminate between
35 incompatible .so files so that extensions for different Python builds can
36 live in the same directory. E.g. foomodule.cpython-32.so
37*/
Guido van Rossum22a1d361999-12-20 21:18:49 +000038
Brett Cannon2657df42012-05-04 15:20:40 -040039const char *_PyImport_DynLoadFiletab[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000040#ifdef __CYGWIN__
Brett Cannon2657df42012-05-04 15:20:40 -040041 ".dll",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000042#else /* !__CYGWIN__ */
Andrew MacIntyred9400542002-02-26 11:41:34 +000043#if defined(PYOS_OS2) && defined(PYCC_GCC)
Brett Cannon2657df42012-05-04 15:20:40 -040044 ".pyd",
45 ".dll",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000046#else /* !(defined(PYOS_OS2) && defined(PYCC_GCC)) */
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000047#ifdef __VMS
Brett Cannon2657df42012-05-04 15:20:40 -040048 ".exe",
49 ".EXE",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000050#else /* !__VMS */
Brett Cannon2657df42012-05-04 15:20:40 -040051 "." SOABI ".so",
52 ".abi" PYTHON_ABI_STRING ".so",
53 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000054#endif /* __VMS */
55#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */
56#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040057 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000058};
59
60static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 dev_t dev;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000062#ifdef __VMS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 ino_t ino[3];
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000064#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 ino_t ino;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000066#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000068} handles[128];
69static int nhandles = 0;
70
71
Victor Stinner42040fb2011-02-22 23:16:19 +000072dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000075 dl_funcptr p;
76 void *handle;
77 char funcname[258];
78 char pathbuf[260];
79 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 if (strchr(pathname, '/') == NULL) {
82 /* Prefix bare filename with "./" */
83 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
84 pathname = pathbuf;
85 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 PyOS_snprintf(funcname, sizeof(funcname),
88 LEAD_UNDERSCORE "PyInit_%.200s", shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000090 if (fp != NULL) {
91 int i;
92 struct stat statb;
Christian Heimes27c4c3e2013-07-20 22:17:55 +020093 if (fstat(fileno(fp), &statb) == -1) {
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070094 PyErr_SetFromErrno(PyExc_IOError);
95 return NULL;
Christian Heimes27c4c3e2013-07-20 22:17:55 +020096 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 for (i = 0; i < nhandles; i++) {
98 if (statb.st_dev == handles[i].dev &&
99 statb.st_ino == handles[i].ino) {
100 p = (dl_funcptr) dlsym(handles[i].handle,
101 funcname);
102 return p;
103 }
104 }
105 if (nhandles < 128) {
106 handles[nhandles].dev = statb.st_dev;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000107#ifdef __VMS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000108 handles[nhandles].ino[0] = statb.st_ino[0];
109 handles[nhandles].ino[1] = statb.st_ino[1];
110 handles[nhandles].ino[2] = statb.st_ino[2];
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000111#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 handles[nhandles].ino = statb.st_ino;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000113#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 }
115 }
Guido van Rossum22a1d361999-12-20 21:18:49 +0000116
Andrew MacIntyred9400542002-02-26 11:41:34 +0000117#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 dlopenflags = PyThreadState_GET()->interp->dlopenflags;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000119#endif
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000120
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000121#ifdef __VMS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 /* VMS currently don't allow a pathname, use a logical name instead */
123 /* Concatenate 'python_module_' and shortname */
124 /* so "import vms.bar" will use the logical python_module_bar */
125 /* As C module use only one name space this is probably not a */
126 /* important limitation */
127 PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
128 shortname);
129 pathname = pathbuf;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000130#endif
131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 if (handle == NULL) {
Brett Cannonf0434e62012-04-20 15:22:50 -0400135 PyObject *mod_name = NULL;
136 PyObject *path = NULL;
137 PyObject *error_ob = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 const char *error = dlerror();
139 if (error == NULL)
140 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400141 error_ob = PyUnicode_FromString(error);
142 path = PyUnicode_FromString(pathname);
143 mod_name = PyUnicode_FromString(shortname);
144 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinnerad54c6d2012-08-22 17:45:52 +0200145 Py_XDECREF(error_ob);
146 Py_XDECREF(path);
147 Py_XDECREF(mod_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 return NULL;
149 }
150 if (fp != NULL && nhandles < 128)
151 handles[nhandles++].handle = handle;
152 p = (dl_funcptr) dlsym(handle, funcname);
153 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000154}