diff options
author | Guido van Rossum <guido@python.org> | 1995-01-02 19:04:15 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1995-01-02 19:04:15 (GMT) |
commit | 1ae940a5870df2f706fa884afd533847f6b0b1a8 (patch) | |
tree | ac19577f141b553bd56f998a62478719d5b81cd4 /Python/importdl.c | |
parent | 824de25fe2edade0ded378b4d602351272f4cf63 (diff) | |
download | cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.zip cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.gz cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.bz2 |
Lots of changes, most minor (fatal() instead of abort(), use of
err_fetch/err_restore and so on). But...
NOTE: import.c has been rewritten and all the DL stuff is now in the
new file importdl.c.
Diffstat (limited to 'Python/importdl.c')
-rw-r--r-- | Python/importdl.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/Python/importdl.c b/Python/importdl.c new file mode 100644 index 0000000..f377c61 --- /dev/null +++ b/Python/importdl.c @@ -0,0 +1,381 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* Support for dynamic loading of extension modules */ +/* If no dynamic linking is supported, this file still generates some code! */ + +#include "allobjects.h" +#include "osdefs.h" +#include "importdl.h" + +extern int verbose; /* Defined in pythonrun.c */ + +/* Explanation of some of the the various #defines used by dynamic linking... + + symbol -- defined for: + + DYNAMIC_LINK -- any kind of dynamic linking + USE_RLD -- NeXT dynamic linking + USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl + USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries + _AIX -- AIX style dynamic linking + NT -- NT style dynamic linking (using DLLs) + _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined + WITH_MAC_DL -- Mac dynamic linking (highly experimental) + SHORT_EXT -- short extension for dynamic module, e.g. ".so" + LONG_EXT -- long extension, e.g. "module.so" + hpux -- HP-UX Dynamic Linking - defined by the compiler + + (The other WITH_* symbols are used only once, to set the + appropriate symbols.) +*/ + +/* Configure dynamic linking */ + +#ifdef hpux +#define DYNAMIC_LINK +#include <errno.h> +typedef void (*dl_funcptr)(); +#define _DL_FUNCPTR_DEFINED 1 +#define SHORT_EXT ".sl" +#define LONG_EXT "module.sl" +#endif + +#ifdef NT +#define DYNAMIC_LINK +#include <windows.h> +typedef FARPROC dl_funcptr; +#define _DL_FUNCPTR_DEFINED +#define SHORT_EXT ".dll" +#define LONG_EXT "module.dll" +#endif + +#if defined(NeXT) || defined(WITH_RLD) +#define DYNAMIC_LINK +#define USE_RLD +#endif + +#ifdef WITH_SGI_DL +#define DYNAMIC_LINK +#define USE_DL +#endif + +#ifdef WITH_DL_DLD +#define DYNAMIC_LINK +#define USE_DL +#endif + +#ifdef WITH_MAC_DL +#define DYNAMIC_LINK +#endif + +#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) +#define DYNAMIC_LINK +#define USE_SHLIB +#endif + +#ifdef _AIX +#define DYNAMIC_LINK +#include <sys/ldr.h> +typedef void (*dl_funcptr)(); +#define _DL_FUNCPTR_DEFINED +static void aix_loaderror(char *name); +#endif + +#ifdef DYNAMIC_LINK + +#ifdef USE_SHLIB +#include <dlfcn.h> +#ifndef _DL_FUNCPTR_DEFINED +typedef void (*dl_funcptr)(); +#endif +#ifndef RTLD_LAZY +#define RTLD_LAZY 1 +#endif +#define SHORT_EXT ".so" +#define LONG_EXT "module.so" +#endif /* USE_SHLIB */ + +#if defined(USE_DL) || defined(hpux) +#include "dl.h" +#endif + +#ifdef WITH_MAC_DL +#include "dynamic_load.h" +#endif + +#ifdef USE_RLD +#include <mach-o/rld.h> +#define FUNCNAME_PATTERN "_init%.200s" +#ifndef _DL_FUNCPTR_DEFINED +typedef void (*dl_funcptr)(); +#endif +#endif /* USE_RLD */ + +extern char *getprogramname(); + +#ifndef FUNCNAME_PATTERN +#if defined(__hp9000s300) +#define FUNCNAME_PATTERN "_init%.200s" +#else +#define FUNCNAME_PATTERN "init%.200s" +#endif +#endif + +#if !defined(SHORT_EXT) && !defined(LONG_EXT) +#define SHORT_EXT ".o" +#define LONG_EXT "module.o" +#endif /* !SHORT_EXT && !LONG_EXT */ + +#endif /* DYNAMIC_LINK */ + +/* Max length of module suffix searched for -- accommodates "module.so" */ +#ifndef MAXSUFFIXSIZE +#define MAXSUFFIXSIZE 10 +#endif + +/* Pass it on to import.c */ +int import_maxsuffixsize = MAXSUFFIXSIZE; + +struct filedescr import_filetab[] = { +#ifdef SHORT_EXT + {SHORT_EXT, "rb", C_EXTENSION}, +#endif /* !SHORT_EXT */ +#ifdef LONG_EXT + {LONG_EXT, "rb", C_EXTENSION}, +#endif /* !LONG_EXT */ + {".py", "r", PY_SOURCE}, + {".pyc", "rb", PY_COMPILED}, + {0, 0} +}; + +object * +load_dynamic_module(name, pathname) + char *name; + char *pathname; +{ +#ifndef DYNAMIC_LINK + err_setstr(ImportError, "dynamically linked modules not supported"); + return NULL; +#else + object *m; + char funcname[258]; + dl_funcptr p = NULL; + if (m != NULL) { + err_setstr(ImportError, + "cannot reload dynamically loaded module"); + return NULL; + } + sprintf(funcname, FUNCNAME_PATTERN, name); +#ifdef WITH_MAC_DL + { + object *v = dynamic_load(pathname); + if (v == NULL) + return NULL; + } +#else /* !WITH_MAC_DL */ +#ifdef USE_SHLIB + { +#ifdef RTLD_NOW + /* RTLD_NOW: resolve externals now + (i.e. core dump now if some are missing) */ + void *handle = dlopen(pathname, RTLD_NOW); +#else + void *handle; + if (verbose) + printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY); + handle = dlopen(pathname, RTLD_LAZY); +#endif /* RTLD_NOW */ + if (handle == NULL) { + err_setstr(ImportError, dlerror()); + return NULL; + } + p = (dl_funcptr) dlsym(handle, funcname); + } +#endif /* USE_SHLIB */ +#ifdef _AIX + p = (dl_funcptr) load(pathname, 1, 0); + if (p == NULL) { + aix_loaderror(pathname); + return NULL; + } +#endif /* _AIX */ +#ifdef NT + { + HINSTANCE hDLL; + hDLL = LoadLibrary(pathname); + if (hDLL==NULL){ + char errBuf[64]; + sprintf(errBuf, "DLL load failed with error code %d", + GetLastError()); + err_setstr(ImportError, errBuf); + return NULL; + } + p = GetProcAddress(hDLL, funcname); + } +#endif /* NT */ +#ifdef USE_DL + p = dl_loadmod(getprogramname(), pathname, funcname); +#endif /* USE_DL */ +#ifdef USE_RLD + { + NXStream *errorStream; + struct mach_header *new_header; + const char *filenames[2]; + long ret; + unsigned long ptr; + + errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); + filenames[0] = pathname; + filenames[1] = NULL; + ret = rld_load(errorStream, &new_header, + filenames, NULL); + + /* extract the error messages for the exception */ + if(!ret) { + char *streamBuf; + int len, maxLen; + + NXPutc(errorStream, (char)0); + + NXGetMemoryBuffer(errorStream, + &streamBuf, &len, &maxLen); + err_setstr(ImportError, streamBuf); + } + + if(ret && rld_lookup(errorStream, funcname, &ptr)) + p = (dl_funcptr) ptr; + + NXCloseMemory(errorStream, NX_FREEBUFFER); + + if(!ret) + return NULL; + } +#endif /* USE_RLD */ +#ifdef hpux + { + shl_t lib; + int flags; + + flags = BIND_DEFERRED; + if (verbose) + { + flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE; + printf("shl_load %s\n",pathname); + } + lib = shl_load(pathname, flags, 0); + if (lib == NULL) + { + char buf[256]; + if (verbose) + perror(pathname); + sprintf(buf, "Failed to load %.200s", pathname); + err_setstr(ImportError, buf); + return NULL; + } + if (verbose) + printf("shl_findsym %s\n", funcname); + shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p); + if (p == NULL && verbose) + perror(funcname); + } +#endif /* hpux */ + if (p == NULL) { + err_setstr(ImportError, + "dynamic module does not define init function"); + return NULL; + } + (*p)(); + +#endif /* !WITH_MAC_DL */ + m = dictlookup(import_modules, name); + if (m == NULL) { + if (err_occurred() == NULL) + err_setstr(SystemError, + "dynamic module not initialized properly"); + return NULL; + } + if (verbose) + fprintf(stderr, + "import %s # dynamically loaded from %s\n", + name, pathname); + INCREF(m); + return m; +#endif /* DYNAMIC_LINK */ +} + + +#ifdef _AIX + +#include <ctype.h> /* for isdigit() */ +#include <errno.h> /* for global errno */ +#include <string.h> /* for strerror() */ + +void aix_loaderror(char *pathname) +{ + + char *message[8], errbuf[1024]; + int i,j; + + struct errtab { + int errno; + char *errstr; + } load_errtab[] = { + {L_ERROR_TOOMANY, "to many errors, rest skipped."}, + {L_ERROR_NOLIB, "can't load library:"}, + {L_ERROR_UNDEF, "can't find symbol in library:"}, + {L_ERROR_RLDBAD, + "RLD index out of range or bad relocation type:"}, + {L_ERROR_FORMAT, "not a valid, executable xcoff file:"}, + {L_ERROR_MEMBER, + "file not an archive or does not contain requested member:"}, + {L_ERROR_TYPE, "symbol table mismatch:"}, + {L_ERROR_ALIGN, "text allignment in file is wrong."}, + {L_ERROR_SYSTEM, "System error:"}, + {L_ERROR_ERRNO, NULL} + }; + +#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) +#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) + + sprintf(errbuf, " from module %.200s ", pathname); + + if (!loadquery(1, &message[0], sizeof(message))) + ERRBUF_APPEND(strerror(errno)); + for(i = 0; message[i] && *message[i]; i++) { + int nerr = atoi(message[i]); + for (j=0; j<LOAD_ERRTAB_LEN ; j++) { + if (nerr == load_errtab[i].errno && load_errtab[i].errstr) + ERRBUF_APPEND(load_errtab[i].errstr); + } + while (isdigit(*message[i])) message[i]++ ; + ERRBUF_APPEND(message[i]); + ERRBUF_APPEND("\n"); + } + errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ + err_setstr(ImportError, errbuf); + return; +} + +#endif /* _AIX */ |