You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
5.8 KiB

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