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.

184 lines
5.7 KiB

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