blob: 7f8f134d60b34549ad2d3463b7bbfc698f2c8d2d [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>
21#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000022
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000023#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
Guido van Rossumc8fcdcb2000-10-25 22:07:45 +000024#define LEAD_UNDERSCORE "_"
25#else
26#define LEAD_UNDERSCORE ""
27#endif
28
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000029/* The .so extension module ABI tag, supplied by the Makefile via
30 Makefile.pre.in and configure. This is used to discriminate between
31 incompatible .so files so that extensions for different Python builds can
32 live in the same directory. E.g. foomodule.cpython-32.so
33*/
Guido van Rossum22a1d361999-12-20 21:18:49 +000034
Brett Cannon2657df42012-05-04 15:20:40 -040035const char *_PyImport_DynLoadFiletab[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000036#ifdef __CYGWIN__
Brett Cannon2657df42012-05-04 15:20:40 -040037 ".dll",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000038#else /* !__CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040039 "." SOABI ".so",
40 ".abi" PYTHON_ABI_STRING ".so",
41 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000042#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040043 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000044};
45
46static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000047 dev_t dev;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 ino_t ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000050} handles[128];
51static int nhandles = 0;
52
53
Nick Coghland5cacbb2015-05-23 22:24:10 +100054dl_funcptr
55_PyImport_FindSharedFuncptr(const char *prefix,
56 const char *shortname,
57 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000059 dl_funcptr p;
60 void *handle;
61 char funcname[258];
62 char pathbuf[260];
63 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 if (strchr(pathname, '/') == NULL) {
66 /* Prefix bare filename with "./" */
67 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
68 pathname = pathbuf;
69 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 PyOS_snprintf(funcname, sizeof(funcname),
Nick Coghland5cacbb2015-05-23 22:24:10 +100072 LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 if (fp != NULL) {
75 int i;
Victor Stinnere134a7f2015-03-30 10:09:31 +020076 struct _Py_stat_struct status;
77 if (_Py_fstat(fileno(fp), &status) == -1)
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070078 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 for (i = 0; i < nhandles; i++) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020080 if (status.st_dev == handles[i].dev &&
81 status.st_ino == handles[i].ino) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 p = (dl_funcptr) dlsym(handles[i].handle,
83 funcname);
84 return p;
85 }
86 }
87 if (nhandles < 128) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020088 handles[nhandles].dev = status.st_dev;
89 handles[nhandles].ino = status.st_ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000090 }
91 }
Guido van Rossum22a1d361999-12-20 21:18:49 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 dlopenflags = PyThreadState_GET()->interp->dlopenflags;
Martin v. Löwisf0473d52001-07-18 16:17:16 +000094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +000096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 if (handle == NULL) {
Victor Stinner3b635cd2012-10-02 00:55:07 +020098 PyObject *mod_name;
99 PyObject *path;
100 PyObject *error_ob;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 const char *error = dlerror();
102 if (error == NULL)
103 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400104 error_ob = PyUnicode_FromString(error);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200105 if (error_ob == NULL)
106 return NULL;
Brett Cannonf0434e62012-04-20 15:22:50 -0400107 mod_name = PyUnicode_FromString(shortname);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200108 if (mod_name == NULL) {
109 Py_DECREF(error_ob);
110 return NULL;
111 }
112 path = PyUnicode_FromString(pathname);
113 if (path == NULL) {
114 Py_DECREF(error_ob);
115 Py_DECREF(mod_name);
116 return NULL;
117 }
Brett Cannonf0434e62012-04-20 15:22:50 -0400118 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200119 Py_DECREF(error_ob);
120 Py_DECREF(mod_name);
121 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 return NULL;
123 }
124 if (fp != NULL && nhandles < 128)
125 handles[nhandles++].handle = handle;
126 p = (dl_funcptr) dlsym(handle, funcname);
127 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000128}