| /* Support for dynamic loading of extension modules */ | |
| #include "Python.h" | |
| #include "importdl.h" | |
| #include <ctype.h> /* for isdigit() */ | |
| #include <errno.h> /* for global errno */ | |
| #include <string.h> /* for strerror() */ | |
| #include <stdlib.h> /* for malloc(), free() */ | |
| #include <sys/ldr.h> | |
| #ifdef AIX_GENUINE_CPLUSPLUS | |
| #include <load.h> | |
| #define aix_load loadAndInit | |
| #else | |
| #define aix_load load | |
| #endif | |
| extern char *Py_GetProgramName(void); | |
| typedef struct Module { | |
| struct Module *next; | |
| void *entry; | |
| } Module, *ModulePtr; | |
| const struct filedescr _PyImport_DynLoadFiletab[] = { | |
| {".so", "rb", C_EXTENSION}, | |
| {"module.so", "rb", C_EXTENSION}, | |
| {0, 0} | |
| }; | |
| static int | |
| aix_getoldmodules(void **modlistptr) | |
| { | |
| register ModulePtr modptr, prevmodptr; | |
| register struct ld_info *ldiptr; | |
| register char *ldibuf; | |
| register int errflag, bufsize = 1024; | |
| register unsigned int offset; | |
| char *progname = Py_GetProgramName(); | |
| /* | |
| -- Get the list of loaded modules into ld_info structures. | |
| */ | |
| if ((ldibuf = malloc(bufsize)) == NULL) { | |
| PyErr_SetString(PyExc_ImportError, strerror(errno)); | |
| return -1; | |
| } | |
| while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1 | |
| && errno == ENOMEM) { | |
| free(ldibuf); | |
| bufsize += 1024; | |
| if ((ldibuf = malloc(bufsize)) == NULL) { | |
| PyErr_SetString(PyExc_ImportError, strerror(errno)); | |
| return -1; | |
| } | |
| } | |
| if (errflag == -1) { | |
| PyErr_SetString(PyExc_ImportError, strerror(errno)); | |
| return -1; | |
| } | |
| /* | |
| -- Make the modules list from the ld_info structures. | |
| */ | |
| ldiptr = (struct ld_info *)ldibuf; | |
| prevmodptr = NULL; | |
| do { | |
| if (strstr(progname, ldiptr->ldinfo_filename) == NULL && | |
| strstr(ldiptr->ldinfo_filename, "python") == NULL) { | |
| /* | |
| -- Extract only the modules belonging to the main | |
| -- executable + those containing "python" as a | |
| -- substring (like the "python[version]" binary or | |
| -- "libpython[version].a" in case it's a shared lib). | |
| */ | |
| offset = (unsigned int)ldiptr->ldinfo_next; | |
| ldiptr = (struct ld_info *)((char*)ldiptr + offset); | |
| continue; | |
| } | |
| if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) { | |
| PyErr_SetString(PyExc_ImportError, strerror(errno)); | |
| while (*modlistptr) { | |
| modptr = (ModulePtr)*modlistptr; | |
| *modlistptr = (void *)modptr->next; | |
| free(modptr); | |
| } | |
| return -1; | |
| } | |
| modptr->entry = ldiptr->ldinfo_dataorg; | |
| modptr->next = NULL; | |
| if (prevmodptr == NULL) | |
| *modlistptr = (void *)modptr; | |
| else | |
| prevmodptr->next = modptr; | |
| prevmodptr = modptr; | |
| offset = (unsigned int)ldiptr->ldinfo_next; | |
| ldiptr = (struct ld_info *)((char*)ldiptr + offset); | |
| } while (offset); | |
| free(ldibuf); | |
| return 0; | |
| } | |
| static void | |
| aix_loaderror(const char *pathname) | |
| { | |
| char *message[1024], errbuf[1024]; | |
| register int i,j; | |
| struct errtab { | |
| int errNo; | |
| char *errstr; | |
| } load_errtab[] = { | |
| {L_ERROR_TOOMANY, "too 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 alignment 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) | |
| PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname); | |
| if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) { | |
| ERRBUF_APPEND(strerror(errno)); | |
| ERRBUF_APPEND("\n"); | |
| } | |
| 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[j].errNo && load_errtab[j].errstr) | |
| ERRBUF_APPEND(load_errtab[j].errstr); | |
| } | |
| while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ; | |
| ERRBUF_APPEND(message[i]); | |
| ERRBUF_APPEND("\n"); | |
| } | |
| errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ | |
| PyErr_SetString(PyExc_ImportError, errbuf); | |
| return; | |
| } | |
| dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, | |
| const char *pathname, FILE *fp) | |
| { | |
| dl_funcptr p; | |
| /* | |
| -- Invoke load() with L_NOAUTODEFER leaving the imported symbols | |
| -- of the shared module unresolved. Thus we have to resolve them | |
| -- explicitly with loadbind. The new module is loaded, then we | |
| -- resolve its symbols using the list of already loaded modules | |
| -- (only those that belong to the python executable). Get these | |
| -- with loadquery(L_GETINFO). | |
| */ | |
| static void *staticmodlistptr = NULL; | |
| if (!staticmodlistptr) | |
| if (aix_getoldmodules(&staticmodlistptr) == -1) | |
| return NULL; | |
| p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0); | |
| if (p == NULL) { | |
| aix_loaderror(pathname); | |
| return NULL; | |
| } | |
| return p; | |
| } |