blob: 082154dd91b1fc87d8810ba9ecd46657a3aa0b9e [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 Stinner4a3fe082020-04-14 14:26:24 +02005#include "pycore_interp.h" // _PyInterpreterState.dlopenflags
Victor Stinner81a7be32020-04-14 15:14:01 +02006#include "pycore_pystate.h" // _PyInterpreterState_GET()
Guido van Rossum22a1d361999-12-20 21:18:49 +00007#include "importdl.h"
8
9#include <sys/types.h>
10#include <sys/stat.h>
Martin v. Löwis8a57f002001-10-18 21:24:04 +000011
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000012#if defined(__NetBSD__)
13#include <sys/param.h>
14#if (NetBSD < 199712)
Guido van Rossum22a1d361999-12-20 21:18:49 +000015#include <nlist.h>
16#include <link.h>
17#define dlerror() "error in dynamic linking"
Martin v. Löwis8a57f002001-10-18 21:24:04 +000018#endif
19#endif /* NetBSD */
20
Guido van Rossum22a1d361999-12-20 21:18:49 +000021#ifdef HAVE_DLFCN_H
22#include <dlfcn.h>
23#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000024
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000025#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
Guido van Rossumc8fcdcb2000-10-25 22:07:45 +000026#define LEAD_UNDERSCORE "_"
27#else
28#define LEAD_UNDERSCORE ""
29#endif
30
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000031/* The .so extension module ABI tag, supplied by the Makefile via
32 Makefile.pre.in and configure. This is used to discriminate between
33 incompatible .so files so that extensions for different Python builds can
34 live in the same directory. E.g. foomodule.cpython-32.so
35*/
Guido van Rossum22a1d361999-12-20 21:18:49 +000036
Brett Cannon2657df42012-05-04 15:20:40 -040037const char *_PyImport_DynLoadFiletab[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000038#ifdef __CYGWIN__
Brett Cannon2657df42012-05-04 15:20:40 -040039 ".dll",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000040#else /* !__CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040041 "." SOABI ".so",
Victor Stinner5422e3c2019-04-26 01:40:00 +020042#ifdef ALT_SOABI
43 "." ALT_SOABI ".so",
44#endif
Brett Cannon2657df42012-05-04 15:20:40 -040045 ".abi" PYTHON_ABI_STRING ".so",
46 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000047#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040048 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000049};
50
51static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 dev_t dev;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 ino_t ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000055} handles[128];
56static int nhandles = 0;
57
58
Nick Coghland5cacbb2015-05-23 22:24:10 +100059dl_funcptr
60_PyImport_FindSharedFuncptr(const char *prefix,
61 const char *shortname,
62 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 dl_funcptr p;
65 void *handle;
66 char funcname[258];
67 char pathbuf[260];
68 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000069
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 if (strchr(pathname, '/') == NULL) {
71 /* Prefix bare filename with "./" */
72 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
73 pathname = pathbuf;
74 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 PyOS_snprintf(funcname, sizeof(funcname),
Nick Coghland5cacbb2015-05-23 22:24:10 +100077 LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 if (fp != NULL) {
80 int i;
Victor Stinnere134a7f2015-03-30 10:09:31 +020081 struct _Py_stat_struct status;
82 if (_Py_fstat(fileno(fp), &status) == -1)
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070083 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 for (i = 0; i < nhandles; i++) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020085 if (status.st_dev == handles[i].dev &&
86 status.st_ino == handles[i].ino) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 p = (dl_funcptr) dlsym(handles[i].handle,
88 funcname);
89 return p;
90 }
91 }
92 if (nhandles < 128) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020093 handles[nhandles].dev = status.st_dev;
94 handles[nhandles].ino = status.st_ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 }
96 }
Guido van Rossum22a1d361999-12-20 21:18:49 +000097
Victor Stinner81a7be32020-04-14 15:14:01 +020098 dlopenflags = _PyInterpreterState_GET()->dlopenflags;
Martin v. Löwisf0473d52001-07-18 16:17:16 +000099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 if (handle == NULL) {
Victor Stinner3b635cd2012-10-02 00:55:07 +0200103 PyObject *mod_name;
104 PyObject *path;
105 PyObject *error_ob;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 const char *error = dlerror();
107 if (error == NULL)
108 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400109 error_ob = PyUnicode_FromString(error);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200110 if (error_ob == NULL)
111 return NULL;
Brett Cannonf0434e62012-04-20 15:22:50 -0400112 mod_name = PyUnicode_FromString(shortname);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200113 if (mod_name == NULL) {
114 Py_DECREF(error_ob);
115 return NULL;
116 }
117 path = PyUnicode_FromString(pathname);
118 if (path == NULL) {
119 Py_DECREF(error_ob);
120 Py_DECREF(mod_name);
121 return NULL;
122 }
Brett Cannonf0434e62012-04-20 15:22:50 -0400123 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200124 Py_DECREF(error_ob);
125 Py_DECREF(mod_name);
126 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 return NULL;
128 }
129 if (fp != NULL && nhandles < 128)
130 handles[nhandles++].handle = handle;
131 p = (dl_funcptr) dlsym(handle, funcname);
132 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000133}