Branch data 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 : 29199 : _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 : 29199 : int dlopenflags=0; 62 : : 63 [ + + ]: 29199 : 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 : 29199 : PyOS_snprintf(funcname, sizeof(funcname), 70 : : LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname); 71 : : 72 [ - + ]: 29199 : 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 : 29199 : dlopenflags = _PyInterpreterState_GET()->dlopenflags; 79 : : 80 : 29199 : handle = dlopen(pathname, dlopenflags); 81 : : 82 [ + + ]: 29199 : if (handle == NULL) { 83 : : PyObject *mod_name; 84 : : PyObject *path; 85 : : PyObject *error_ob; 86 : 1 : const char *error = dlerror(); 87 [ - + ]: 1 : if (error == NULL) 88 : 0 : error = "unknown dlopen() error"; 89 : 1 : error_ob = PyUnicode_DecodeLocale(error, "surrogateescape"); 90 [ - + ]: 1 : if (error_ob == NULL) 91 : 0 : return NULL; 92 : 1 : mod_name = PyUnicode_FromString(shortname); 93 [ - + ]: 1 : if (mod_name == NULL) { 94 : 0 : Py_DECREF(error_ob); 95 : 0 : return NULL; 96 : : } 97 : 1 : path = PyUnicode_DecodeFSDefault(pathname); 98 [ - + ]: 1 : if (path == NULL) { 99 : 0 : Py_DECREF(error_ob); 100 : 0 : Py_DECREF(mod_name); 101 : 0 : return NULL; 102 : : } 103 : 1 : PyErr_SetImportError(error_ob, mod_name, path); 104 : 1 : Py_DECREF(error_ob); 105 : 1 : Py_DECREF(mod_name); 106 : 1 : Py_DECREF(path); 107 : 1 : return NULL; 108 : : } 109 : 29198 : p = (dl_funcptr) dlsym(handle, funcname); 110 : 29198 : return p; 111 : : }