blob: feebd8976d0adb14ec19d6ba475ef6e62d435b9a [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"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pystate.h"
Guido van Rossum22a1d361999-12-20 21:18:49 +00006#include "importdl.h"
7
8#include <sys/types.h>
9#include <sys/stat.h>
Martin v. Löwis8a57f002001-10-18 21:24:04 +000010
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000011#if defined(__NetBSD__)
12#include <sys/param.h>
13#if (NetBSD < 199712)
Guido van Rossum22a1d361999-12-20 21:18:49 +000014#include <nlist.h>
15#include <link.h>
16#define dlerror() "error in dynamic linking"
Martin v. Löwis8a57f002001-10-18 21:24:04 +000017#endif
18#endif /* NetBSD */
19
Guido van Rossum22a1d361999-12-20 21:18:49 +000020#ifdef HAVE_DLFCN_H
21#include <dlfcn.h>
22#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000023
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000024#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
Guido van Rossumc8fcdcb2000-10-25 22:07:45 +000025#define LEAD_UNDERSCORE "_"
26#else
27#define LEAD_UNDERSCORE ""
28#endif
29
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000030/* The .so extension module ABI tag, supplied by the Makefile via
31 Makefile.pre.in and configure. This is used to discriminate between
32 incompatible .so files so that extensions for different Python builds can
33 live in the same directory. E.g. foomodule.cpython-32.so
34*/
Guido van Rossum22a1d361999-12-20 21:18:49 +000035
Brett Cannon2657df42012-05-04 15:20:40 -040036const char *_PyImport_DynLoadFiletab[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000037#ifdef __CYGWIN__
Brett Cannon2657df42012-05-04 15:20:40 -040038 ".dll",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000039#else /* !__CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040040 "." SOABI ".so",
41 ".abi" PYTHON_ABI_STRING ".so",
42 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000043#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040044 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000045};
46
47static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 dev_t dev;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 ino_t ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000051} handles[128];
52static int nhandles = 0;
53
54
Nick Coghland5cacbb2015-05-23 22:24:10 +100055dl_funcptr
56_PyImport_FindSharedFuncptr(const char *prefix,
57 const char *shortname,
58 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000059{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 dl_funcptr p;
61 void *handle;
62 char funcname[258];
63 char pathbuf[260];
64 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 if (strchr(pathname, '/') == NULL) {
67 /* Prefix bare filename with "./" */
68 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
69 pathname = pathbuf;
70 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 PyOS_snprintf(funcname, sizeof(funcname),
Nick Coghland5cacbb2015-05-23 22:24:10 +100073 LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000075 if (fp != NULL) {
76 int i;
Victor Stinnere134a7f2015-03-30 10:09:31 +020077 struct _Py_stat_struct status;
78 if (_Py_fstat(fileno(fp), &status) == -1)
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070079 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 for (i = 0; i < nhandles; i++) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020081 if (status.st_dev == handles[i].dev &&
82 status.st_ino == handles[i].ino) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 p = (dl_funcptr) dlsym(handles[i].handle,
84 funcname);
85 return p;
86 }
87 }
88 if (nhandles < 128) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020089 handles[nhandles].dev = status.st_dev;
90 handles[nhandles].ino = status.st_ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 }
92 }
Guido van Rossum22a1d361999-12-20 21:18:49 +000093
Victor Stinnercaba55b2018-08-03 15:33:52 +020094 dlopenflags = _PyInterpreterState_Get()->dlopenflags;
Martin v. Löwisf0473d52001-07-18 16:17:16 +000095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +000097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 if (handle == NULL) {
Victor Stinner3b635cd2012-10-02 00:55:07 +020099 PyObject *mod_name;
100 PyObject *path;
101 PyObject *error_ob;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 const char *error = dlerror();
103 if (error == NULL)
104 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400105 error_ob = PyUnicode_FromString(error);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200106 if (error_ob == NULL)
107 return NULL;
Brett Cannonf0434e62012-04-20 15:22:50 -0400108 mod_name = PyUnicode_FromString(shortname);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200109 if (mod_name == NULL) {
110 Py_DECREF(error_ob);
111 return NULL;
112 }
113 path = PyUnicode_FromString(pathname);
114 if (path == NULL) {
115 Py_DECREF(error_ob);
116 Py_DECREF(mod_name);
117 return NULL;
118 }
Brett Cannonf0434e62012-04-20 15:22:50 -0400119 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200120 Py_DECREF(error_ob);
121 Py_DECREF(mod_name);
122 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 return NULL;
124 }
125 if (fp != NULL && nhandles < 128)
126 handles[nhandles++].handle = handle;
127 p = (dl_funcptr) dlsym(handle, funcname);
128 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000129}