1 2/* Support for dynamic loading of extension modules */ 3 4#include "Python.h" 5#include "importdl.h" 6 7#include <ctype.h> /* for isdigit() */ 8#include <errno.h> /* for global errno */ 9#include <string.h> /* for strerror() */ 10#include <stdlib.h> /* for malloc(), free() */ 11#include <sys/ldr.h> 12 13 14#ifdef AIX_GENUINE_CPLUSPLUS 15#include <load.h> 16#define aix_load loadAndInit 17#else 18#define aix_load load 19#endif 20 21 22extern char *Py_GetProgramName(void); 23 24typedef struct Module { 25 struct Module *next; 26 void *entry; 27} Module, *ModulePtr; 28 29const struct filedescr _PyImport_DynLoadFiletab[] = { 30 {".so", "rb", C_EXTENSION}, 31 {"module.so", "rb", C_EXTENSION}, 32 {0, 0} 33}; 34 35static int 36aix_getoldmodules(void **modlistptr) 37{ 38 register ModulePtr modptr, prevmodptr; 39 register struct ld_info *ldiptr; 40 register char *ldibuf; 41 register int errflag, bufsize = 1024; 42 register unsigned int offset; 43 char *progname = Py_GetProgramName(); 44 45 /* 46 -- Get the list of loaded modules into ld_info structures. 47 */ 48 if ((ldibuf = malloc(bufsize)) == NULL) { 49 PyErr_SetString(PyExc_ImportError, strerror(errno)); 50 return -1; 51 } 52 while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1 53 && errno == ENOMEM) { 54 free(ldibuf); 55 bufsize += 1024; 56 if ((ldibuf = malloc(bufsize)) == NULL) { 57 PyErr_SetString(PyExc_ImportError, strerror(errno)); 58 return -1; 59 } 60 } 61 if (errflag == -1) { 62 PyErr_SetString(PyExc_ImportError, strerror(errno)); 63 return -1; 64 } 65 /* 66 -- Make the modules list from the ld_info structures. 67 */ 68 ldiptr = (struct ld_info *)ldibuf; 69 prevmodptr = NULL; 70 do { 71 if (strstr(progname, ldiptr->ldinfo_filename) == NULL && 72 strstr(ldiptr->ldinfo_filename, "python") == NULL) { 73 /* 74 -- Extract only the modules belonging to the main 75 -- executable + those containing "python" as a 76 -- substring (like the "python[version]" binary or 77 -- "libpython[version].a" in case it's a shared lib). 78 */ 79 offset = (unsigned int)ldiptr->ldinfo_next; 80 ldiptr = (struct ld_info *)((char*)ldiptr + offset); 81 continue; 82 } 83 if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) { 84 PyErr_SetString(PyExc_ImportError, strerror(errno)); 85 while (*modlistptr) { 86 modptr = (ModulePtr)*modlistptr; 87 *modlistptr = (void *)modptr->next; 88 free(modptr); 89 } 90 return -1; 91 } 92 modptr->entry = ldiptr->ldinfo_dataorg; 93 modptr->next = NULL; 94 if (prevmodptr == NULL) 95 *modlistptr = (void *)modptr; 96 else 97 prevmodptr->next = modptr; 98 prevmodptr = modptr; 99 offset = (unsigned int)ldiptr->ldinfo_next; 100 ldiptr = (struct ld_info *)((char*)ldiptr + offset); 101 } while (offset); 102 free(ldibuf); 103 return 0; 104} 105 106 107static void 108aix_loaderror(const char *pathname) 109{ 110 111 char *message[1024], errbuf[1024]; 112 register int i,j; 113 114 struct errtab { 115 int errNo; 116 char *errstr; 117 } load_errtab[] = { 118 {L_ERROR_TOOMANY, "too many errors, rest skipped."}, 119 {L_ERROR_NOLIB, "can't load library:"}, 120 {L_ERROR_UNDEF, "can't find symbol in library:"}, 121 {L_ERROR_RLDBAD, 122 "RLD index out of range or bad relocation type:"}, 123 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"}, 124 {L_ERROR_MEMBER, 125 "file not an archive or does not contain requested member:"}, 126 {L_ERROR_TYPE, "symbol table mismatch:"}, 127 {L_ERROR_ALIGN, "text alignment in file is wrong."}, 128 {L_ERROR_SYSTEM, "System error:"}, 129 {L_ERROR_ERRNO, NULL} 130 }; 131 132#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) 133#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) 134 135 PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname); 136 137 if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) { 138 ERRBUF_APPEND(strerror(errno)); 139 ERRBUF_APPEND("\n"); 140 } 141 for(i = 0; message[i] && *message[i]; i++) { 142 int nerr = atoi(message[i]); 143 for (j=0; j<LOAD_ERRTAB_LEN ; j++) { 144 if (nerr == load_errtab[j].errNo && load_errtab[j].errstr) 145 ERRBUF_APPEND(load_errtab[j].errstr); 146 } 147 while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ; 148 ERRBUF_APPEND(message[i]); 149 ERRBUF_APPEND("\n"); 150 } 151 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ 152 PyErr_SetString(PyExc_ImportError, errbuf); 153 return; 154} 155 156 157dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, 158 const char *pathname, FILE *fp) 159{ 160 dl_funcptr p; 161 162 /* 163 -- Invoke load() with L_NOAUTODEFER leaving the imported symbols 164 -- of the shared module unresolved. Thus we have to resolve them 165 -- explicitly with loadbind. The new module is loaded, then we 166 -- resolve its symbols using the list of already loaded modules 167 -- (only those that belong to the python executable). Get these 168 -- with loadquery(L_GETINFO). 169 */ 170 171 static void *staticmodlistptr = NULL; 172 173 if (!staticmodlistptr) 174 if (aix_getoldmodules(&staticmodlistptr) == -1) 175 return NULL; 176 p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0); 177 if (p == NULL) { 178 aix_loaderror(pathname); 179 return NULL; 180 } 181 182 return p; 183} 184