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