Line data Source code
1 : 2 : /* Support for dynamic loading of extension modules */ 3 : 4 : #include "Python.h" 5 : #include "pycore_interp.h" // _PyInterpreterState.dlopenflags 6 : #include "pycore_pystate.h" // _PyInterpreterState_GET() 7 : #include "importdl.h" 8 : 9 : #include <sys/types.h> 10 : #include <sys/stat.h> 11 : 12 : #if defined(__NetBSD__) 13 : #include <sys/param.h> 14 : #if (NetBSD < 199712) 15 : #include <nlist.h> 16 : #include <link.h> 17 : #define dlerror() "error in dynamic linking" 18 : #endif 19 : #endif /* NetBSD */ 20 : 21 : #ifdef HAVE_DLFCN_H 22 : #include <dlfcn.h> 23 : #endif 24 : 25 : #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__) 26 : #define LEAD_UNDERSCORE "_" 27 : #else 28 : #define LEAD_UNDERSCORE "" 29 : #endif 30 : 31 : /* 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 : */ 36 : 37 : const char *_PyImport_DynLoadFiletab[] = { 38 : #ifdef __CYGWIN__ 39 : ".dll", 40 : #else /* !__CYGWIN__ */ 41 : "." SOABI ".so", 42 : #ifdef ALT_SOABI 43 : "." ALT_SOABI ".so", 44 : #endif 45 : ".abi" PYTHON_ABI_STRING ".so", 46 : ".so", 47 : #endif /* __CYGWIN__ */ 48 : NULL, 49 : }; 50 : 51 : 52 : dl_funcptr 53 29403 : _PyImport_FindSharedFuncptr(const char *prefix, 54 : const char *shortname, 55 : const char *pathname, FILE *fp) 56 : { 57 : dl_funcptr p; 58 : void *handle; 59 : char funcname[258]; 60 : char pathbuf[260]; 61 29403 : int dlopenflags=0; 62 : 63 29403 : if (strchr(pathname, '/') == NULL) { 64 : /* Prefix bare filename with "./" */ 65 1 : PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname); 66 1 : pathname = pathbuf; 67 : } 68 : 69 29403 : PyOS_snprintf(funcname, sizeof(funcname), 70 : LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname); 71 : 72 29403 : if (fp != NULL) { 73 : struct _Py_stat_struct status; 74 0 : if (_Py_fstat(fileno(fp), &status) == -1) 75 0 : return NULL; 76 : } 77 : 78 29403 : dlopenflags = _PyInterpreterState_GET()->dlopenflags; 79 : 80 29403 : handle = dlopen(pathname, dlopenflags); 81 : 82 29403 : if (handle == NULL) { 83 : PyObject *mod_name; 84 : PyObject *path; 85 : PyObject *error_ob; 86 47 : const char *error = dlerror(); 87 47 : if (error == NULL) 88 0 : error = "unknown dlopen() error"; 89 47 : error_ob = PyUnicode_DecodeLocale(error, "surrogateescape"); 90 47 : if (error_ob == NULL) 91 0 : return NULL; 92 47 : mod_name = PyUnicode_FromString(shortname); 93 47 : if (mod_name == NULL) { 94 0 : Py_DECREF(error_ob); 95 0 : return NULL; 96 : } 97 47 : path = PyUnicode_DecodeFSDefault(pathname); 98 47 : if (path == NULL) { 99 0 : Py_DECREF(error_ob); 100 0 : Py_DECREF(mod_name); 101 0 : return NULL; 102 : } 103 47 : PyErr_SetImportError(error_ob, mod_name, path); 104 47 : Py_DECREF(error_ob); 105 47 : Py_DECREF(mod_name); 106 47 : Py_DECREF(path); 107 47 : return NULL; 108 : } 109 29356 : p = (dl_funcptr) dlsym(handle, funcname); 110 29356 : return p; 111 : }