blob: e5bddaab6caa0694fea760524cb31e8e5f47c869 [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",
Stefano Rivera338d54f2018-11-16 15:52:52 -080041#ifndef Py_DEBUG
Brett Cannon2657df42012-05-04 15:20:40 -040042 ".abi" PYTHON_ABI_STRING ".so",
Stefano Rivera338d54f2018-11-16 15:52:52 -080043#endif /* ! Py_DEBUG */
Brett Cannon2657df42012-05-04 15:20:40 -040044 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000045#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040046 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000047};
48
49static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 dev_t dev;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 ino_t ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000053} handles[128];
54static int nhandles = 0;
55
56
Nick Coghland5cacbb2015-05-23 22:24:10 +100057dl_funcptr
58_PyImport_FindSharedFuncptr(const char *prefix,
59 const char *shortname,
60 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000061{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 dl_funcptr p;
63 void *handle;
64 char funcname[258];
65 char pathbuf[260];
66 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 if (strchr(pathname, '/') == NULL) {
69 /* Prefix bare filename with "./" */
70 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
71 pathname = pathbuf;
72 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 PyOS_snprintf(funcname, sizeof(funcname),
Nick Coghland5cacbb2015-05-23 22:24:10 +100075 LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (fp != NULL) {
78 int i;
Victor Stinnere134a7f2015-03-30 10:09:31 +020079 struct _Py_stat_struct status;
80 if (_Py_fstat(fileno(fp), &status) == -1)
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070081 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 for (i = 0; i < nhandles; i++) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020083 if (status.st_dev == handles[i].dev &&
84 status.st_ino == handles[i].ino) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 p = (dl_funcptr) dlsym(handles[i].handle,
86 funcname);
87 return p;
88 }
89 }
90 if (nhandles < 128) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020091 handles[nhandles].dev = status.st_dev;
92 handles[nhandles].ino = status.st_ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 }
94 }
Guido van Rossum22a1d361999-12-20 21:18:49 +000095
Victor Stinnercaba55b2018-08-03 15:33:52 +020096 dlopenflags = _PyInterpreterState_Get()->dlopenflags;
Martin v. Löwisf0473d52001-07-18 16:17:16 +000097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +000099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 if (handle == NULL) {
Victor Stinner3b635cd2012-10-02 00:55:07 +0200101 PyObject *mod_name;
102 PyObject *path;
103 PyObject *error_ob;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 const char *error = dlerror();
105 if (error == NULL)
106 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400107 error_ob = PyUnicode_FromString(error);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200108 if (error_ob == NULL)
109 return NULL;
Brett Cannonf0434e62012-04-20 15:22:50 -0400110 mod_name = PyUnicode_FromString(shortname);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200111 if (mod_name == NULL) {
112 Py_DECREF(error_ob);
113 return NULL;
114 }
115 path = PyUnicode_FromString(pathname);
116 if (path == NULL) {
117 Py_DECREF(error_ob);
118 Py_DECREF(mod_name);
119 return NULL;
120 }
Brett Cannonf0434e62012-04-20 15:22:50 -0400121 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200122 Py_DECREF(error_ob);
123 Py_DECREF(mod_name);
124 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000125 return NULL;
126 }
127 if (fp != NULL && nhandles < 128)
128 handles[nhandles++].handle = handle;
129 p = (dl_funcptr) dlsym(handle, funcname);
130 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000131}