blob: c51f97abd286306ac4bf981945acdd0668e5a251 [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",
Victor Stinner5422e3c2019-04-26 01:40:00 +020041#ifdef ALT_SOABI
42 "." ALT_SOABI ".so",
43#endif
Brett Cannon2657df42012-05-04 15:20:40 -040044 ".abi" PYTHON_ABI_STRING ".so",
45 ".so",
Barry Warsaw35f3a2c2010-09-03 18:30:30 +000046#endif /* __CYGWIN__ */
Brett Cannon2657df42012-05-04 15:20:40 -040047 NULL,
Guido van Rossum22a1d361999-12-20 21:18:49 +000048};
49
50static struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 dev_t dev;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 ino_t ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 void *handle;
Guido van Rossum22a1d361999-12-20 21:18:49 +000054} handles[128];
55static int nhandles = 0;
56
57
Nick Coghland5cacbb2015-05-23 22:24:10 +100058dl_funcptr
59_PyImport_FindSharedFuncptr(const char *prefix,
60 const char *shortname,
61 const char *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +000062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 dl_funcptr p;
64 void *handle;
65 char funcname[258];
66 char pathbuf[260];
67 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 if (strchr(pathname, '/') == NULL) {
70 /* Prefix bare filename with "./" */
71 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
72 pathname = pathbuf;
73 }
Guido van Rossum96a8fb71999-12-22 14:09:35 +000074
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000075 PyOS_snprintf(funcname, sizeof(funcname),
Nick Coghland5cacbb2015-05-23 22:24:10 +100076 LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 if (fp != NULL) {
79 int i;
Victor Stinnere134a7f2015-03-30 10:09:31 +020080 struct _Py_stat_struct status;
81 if (_Py_fstat(fileno(fp), &status) == -1)
Benjamin Peterson7d28b6b2013-07-22 22:08:09 -070082 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 for (i = 0; i < nhandles; i++) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020084 if (status.st_dev == handles[i].dev &&
85 status.st_ino == handles[i].ino) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 p = (dl_funcptr) dlsym(handles[i].handle,
87 funcname);
88 return p;
89 }
90 }
91 if (nhandles < 128) {
Victor Stinnere134a7f2015-03-30 10:09:31 +020092 handles[nhandles].dev = status.st_dev;
93 handles[nhandles].ino = status.st_ino;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 }
95 }
Guido van Rossum22a1d361999-12-20 21:18:49 +000096
Victor Stinnercaba55b2018-08-03 15:33:52 +020097 dlopenflags = _PyInterpreterState_Get()->dlopenflags;
Martin v. Löwisf0473d52001-07-18 16:17:16 +000098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 handle = dlopen(pathname, dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000100
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 if (handle == NULL) {
Victor Stinner3b635cd2012-10-02 00:55:07 +0200102 PyObject *mod_name;
103 PyObject *path;
104 PyObject *error_ob;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 const char *error = dlerror();
106 if (error == NULL)
107 error = "unknown dlopen() error";
Brett Cannonf0434e62012-04-20 15:22:50 -0400108 error_ob = PyUnicode_FromString(error);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200109 if (error_ob == NULL)
110 return NULL;
Brett Cannonf0434e62012-04-20 15:22:50 -0400111 mod_name = PyUnicode_FromString(shortname);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200112 if (mod_name == NULL) {
113 Py_DECREF(error_ob);
114 return NULL;
115 }
116 path = PyUnicode_FromString(pathname);
117 if (path == NULL) {
118 Py_DECREF(error_ob);
119 Py_DECREF(mod_name);
120 return NULL;
121 }
Brett Cannonf0434e62012-04-20 15:22:50 -0400122 PyErr_SetImportError(error_ob, mod_name, path);
Victor Stinner3b635cd2012-10-02 00:55:07 +0200123 Py_DECREF(error_ob);
124 Py_DECREF(mod_name);
125 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 return NULL;
127 }
128 if (fp != NULL && nhandles < 128)
129 handles[nhandles++].handle = handle;
130 p = (dl_funcptr) dlsym(handle, funcname);
131 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000132}