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.

183 lines
5.7 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. {"module.so", "rb", C_EXTENSION},
  23. {0, 0}
  24. };
  25. static int
  26. aix_getoldmodules(void **modlistptr)
  27. {
  28. register ModulePtr modptr, prevmodptr;
  29. register struct ld_info *ldiptr;
  30. register char *ldibuf;
  31. register int errflag, bufsize = 1024;
  32. register unsigned int offset;
  33. char *progname = Py_GetProgramName();
  34. /*
  35. -- Get the list of loaded modules into ld_info structures.
  36. */
  37. if ((ldibuf = malloc(bufsize)) == NULL) {
  38. PyErr_SetString(PyExc_ImportError, strerror(errno));
  39. return -1;
  40. }
  41. while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
  42. && errno == ENOMEM) {
  43. free(ldibuf);
  44. bufsize += 1024;
  45. if ((ldibuf = malloc(bufsize)) == NULL) {
  46. PyErr_SetString(PyExc_ImportError, strerror(errno));
  47. return -1;
  48. }
  49. }
  50. if (errflag == -1) {
  51. PyErr_SetString(PyExc_ImportError, strerror(errno));
  52. return -1;
  53. }
  54. /*
  55. -- Make the modules list from the ld_info structures.
  56. */
  57. ldiptr = (struct ld_info *)ldibuf;
  58. prevmodptr = NULL;
  59. do {
  60. if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
  61. strstr(ldiptr->ldinfo_filename, "python") == NULL) {
  62. /*
  63. -- Extract only the modules belonging to the main
  64. -- executable + those containing "python" as a
  65. -- substring (like the "python[version]" binary or
  66. -- "libpython[version].a" in case it's a shared lib).
  67. */
  68. offset = (unsigned int)ldiptr->ldinfo_next;
  69. ldiptr = (struct ld_info *)((char*)ldiptr + offset);
  70. continue;
  71. }
  72. if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
  73. PyErr_SetString(PyExc_ImportError, strerror(errno));
  74. while (*modlistptr) {
  75. modptr = (ModulePtr)*modlistptr;
  76. *modlistptr = (void *)modptr->next;
  77. free(modptr);
  78. }
  79. return -1;
  80. }
  81. modptr->entry = ldiptr->ldinfo_dataorg;
  82. modptr->next = NULL;
  83. if (prevmodptr == NULL)
  84. *modlistptr = (void *)modptr;
  85. else
  86. prevmodptr->next = modptr;
  87. prevmodptr = modptr;
  88. offset = (unsigned int)ldiptr->ldinfo_next;
  89. ldiptr = (struct ld_info *)((char*)ldiptr + offset);
  90. } while (offset);
  91. free(ldibuf);
  92. return 0;
  93. }
  94. static void
  95. aix_loaderror(const char *pathname)
  96. {
  97. char *message[1024], errbuf[1024];
  98. register int i,j;
  99. struct errtab {
  100. int errNo;
  101. char *errstr;
  102. } load_errtab[] = {
  103. {L_ERROR_TOOMANY, "too many errors, rest skipped."},
  104. {L_ERROR_NOLIB, "can't load library:"},
  105. {L_ERROR_UNDEF, "can't find symbol in library:"},
  106. {L_ERROR_RLDBAD,
  107. "RLD index out of range or bad relocation type:"},
  108. {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
  109. {L_ERROR_MEMBER,
  110. "file not an archive or does not contain requested member:"},
  111. {L_ERROR_TYPE, "symbol table mismatch:"},
  112. {L_ERROR_ALIGN, "text alignment in file is wrong."},
  113. {L_ERROR_SYSTEM, "System error:"},
  114. {L_ERROR_ERRNO, NULL}
  115. };
  116. #define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
  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<LOAD_ERRTAB_LEN ; 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. PyErr_SetString(PyExc_ImportError, errbuf);
  135. return;
  136. }
  137. dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
  138. const char *pathname, FILE *fp)
  139. {
  140. dl_funcptr p;
  141. /*
  142. -- Invoke load() with L_NOAUTODEFER leaving the imported symbols
  143. -- of the shared module unresolved. Thus we have to resolve them
  144. -- explicitly with loadbind. The new module is loaded, then we
  145. -- resolve its symbols using the list of already loaded modules
  146. -- (only those that belong to the python executable). Get these
  147. -- with loadquery(L_GETINFO).
  148. */
  149. static void *staticmodlistptr = NULL;
  150. if (!staticmodlistptr)
  151. if (aix_getoldmodules(&staticmodlistptr) == -1)
  152. return NULL;
  153. p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
  154. if (p == NULL) {
  155. aix_loaderror(pathname);
  156. return NULL;
  157. }
  158. return p;
  159. }