blob: 01d9c169866164382e9d40903f6f99044b09ee91 [file] [log] [blame]
Guido van Rossum1ae940a1995-01-02 19:04:15 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum1ae940a1995-01-02 19:04:15 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Support for dynamic loading of extension modules */
26/* If no dynamic linking is supported, this file still generates some code! */
27
28#include "allobjects.h"
29#include "osdefs.h"
30#include "importdl.h"
31
32extern int verbose; /* Defined in pythonrun.c */
33
34/* Explanation of some of the the various #defines used by dynamic linking...
35
36 symbol -- defined for:
37
38 DYNAMIC_LINK -- any kind of dynamic linking
Guido van Rossum75f288d1995-06-14 22:07:26 +000039 USE_RLD -- NeXT dynamic linking
Guido van Rossum1ae940a1995-01-02 19:04:15 +000040 USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl
41 USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries
42 _AIX -- AIX style dynamic linking
43 NT -- NT style dynamic linking (using DLLs)
44 _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined
Jack Jansen5d9acb61995-06-14 14:54:25 +000045 USE_MAC_DYNAMIC_LOADING -- Mac CFM shared libraries
Guido van Rossum1ae940a1995-01-02 19:04:15 +000046 SHORT_EXT -- short extension for dynamic module, e.g. ".so"
47 LONG_EXT -- long extension, e.g. "module.so"
48 hpux -- HP-UX Dynamic Linking - defined by the compiler
Guido van Rossum46c76a61995-01-20 16:53:54 +000049 __NetBSD__ -- NetBSD shared libraries (not quite SVR4 compatible)
Guido van Rossum1ae940a1995-01-02 19:04:15 +000050
51 (The other WITH_* symbols are used only once, to set the
52 appropriate symbols.)
53*/
54
55/* Configure dynamic linking */
56
57#ifdef hpux
58#define DYNAMIC_LINK
59#include <errno.h>
60typedef void (*dl_funcptr)();
61#define _DL_FUNCPTR_DEFINED 1
62#define SHORT_EXT ".sl"
63#define LONG_EXT "module.sl"
64#endif
65
Guido van Rossum46c76a61995-01-20 16:53:54 +000066#ifdef __NetBSD__
67#define DYNAMIC_LINK
68#define USE_SHLIB
69
70#define dlerror() "error in dynamic linking"
71#endif
72
Guido van Rossum0fbec641995-02-27 10:15:36 +000073#ifdef __WIN32__
74#define NT
75#endif
76
Guido van Rossum1ae940a1995-01-02 19:04:15 +000077#ifdef NT
78#define DYNAMIC_LINK
79#include <windows.h>
80typedef FARPROC dl_funcptr;
81#define _DL_FUNCPTR_DEFINED
Guido van Rossum5fb1da71995-01-07 12:36:02 +000082#define SHORT_EXT ".pyd"
83#define LONG_EXT "module.pyd"
Guido van Rossum1ae940a1995-01-02 19:04:15 +000084#endif
85
Guido van Rossum75f288d1995-06-14 22:07:26 +000086#ifdef NeXT
Guido van Rossum1ae940a1995-01-02 19:04:15 +000087#define DYNAMIC_LINK
88#define USE_RLD
89#endif
90
91#ifdef WITH_SGI_DL
92#define DYNAMIC_LINK
93#define USE_DL
94#endif
95
96#ifdef WITH_DL_DLD
97#define DYNAMIC_LINK
98#define USE_DL
99#endif
100
Guido van Rossum6a75d261995-02-18 14:51:15 +0000101#ifdef __CFM68K__
Jack Jansen5d9acb61995-06-14 14:54:25 +0000102#define USE_MAC_DYNAMIC_LOADING
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000103#endif
104
Jack Jansen5d9acb61995-06-14 14:54:25 +0000105#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen4e043731995-02-13 22:42:34 +0000106#define DYNAMIC_LINK
Guido van Rossum6a75d261995-02-18 14:51:15 +0000107#define SHORT_EXT ".slb"
108#define LONG_EXT "module.slb"
Jack Jansen4e043731995-02-13 22:42:34 +0000109#ifndef _DL_FUNCPTR_DEFINED
110typedef void (*dl_funcptr)();
111#endif
112#endif
113
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000114#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
115#define DYNAMIC_LINK
116#define USE_SHLIB
117#endif
118
119#ifdef _AIX
120#define DYNAMIC_LINK
121#include <sys/ldr.h>
122typedef void (*dl_funcptr)();
123#define _DL_FUNCPTR_DEFINED
124static void aix_loaderror(char *name);
125#endif
126
127#ifdef DYNAMIC_LINK
128
129#ifdef USE_SHLIB
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000130#include <sys/types.h>
131#include <sys/stat.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000132#ifdef __NetBSD__
133#include <nlist.h>
134#include <link.h>
135#else
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000136#include <dlfcn.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000137#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000138#ifndef _DL_FUNCPTR_DEFINED
139typedef void (*dl_funcptr)();
140#endif
141#ifndef RTLD_LAZY
142#define RTLD_LAZY 1
143#endif
144#define SHORT_EXT ".so"
145#define LONG_EXT "module.so"
146#endif /* USE_SHLIB */
147
148#if defined(USE_DL) || defined(hpux)
149#include "dl.h"
150#endif
151
Jack Jansen5d9acb61995-06-14 14:54:25 +0000152#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen0a72e8d1995-10-23 13:54:01 +0000153#include <Aliases.h>
Jack Jansen4e043731995-02-13 22:42:34 +0000154#include <CodeFragments.h>
Jack Janseneceb3e31995-06-27 13:15:15 +0000155#ifdef SYMANTEC__CFM68K__ /* Really just an older version of Universal Headers */
Guido van Rossum6a75d261995-02-18 14:51:15 +0000156#define CFragConnectionID ConnectionID
157#define kLoadCFrag 0x01
158#endif
Jack Jansen4e043731995-02-13 22:42:34 +0000159#include <Files.h>
160#include "macdefs.h"
161#include "macglue.h"
162#endif
163
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000164#ifdef USE_RLD
165#include <mach-o/rld.h>
166#define FUNCNAME_PATTERN "_init%.200s"
167#ifndef _DL_FUNCPTR_DEFINED
168typedef void (*dl_funcptr)();
169#endif
170#endif /* USE_RLD */
171
172extern char *getprogramname();
173
174#ifndef FUNCNAME_PATTERN
Guido van Rossum0fbec641995-02-27 10:15:36 +0000175#if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000176#define FUNCNAME_PATTERN "_init%.200s"
177#else
178#define FUNCNAME_PATTERN "init%.200s"
179#endif
180#endif
181
182#if !defined(SHORT_EXT) && !defined(LONG_EXT)
183#define SHORT_EXT ".o"
184#define LONG_EXT "module.o"
185#endif /* !SHORT_EXT && !LONG_EXT */
186
187#endif /* DYNAMIC_LINK */
188
Guido van Rossum6a75d261995-02-18 14:51:15 +0000189/* Max length of module suffix searched for -- accommodates "module.slb" */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000190#ifndef MAXSUFFIXSIZE
Jack Jansen4e043731995-02-13 22:42:34 +0000191#define MAXSUFFIXSIZE 12
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000192#endif
193
194/* Pass it on to import.c */
195int import_maxsuffixsize = MAXSUFFIXSIZE;
196
197struct filedescr import_filetab[] = {
198#ifdef SHORT_EXT
199 {SHORT_EXT, "rb", C_EXTENSION},
200#endif /* !SHORT_EXT */
201#ifdef LONG_EXT
202 {LONG_EXT, "rb", C_EXTENSION},
203#endif /* !LONG_EXT */
204 {".py", "r", PY_SOURCE},
205 {".pyc", "rb", PY_COMPILED},
206 {0, 0}
207};
208
209object *
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000210load_dynamic_module(name, pathname, fp)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000211 char *name;
212 char *pathname;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000213 FILE *fp;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000214{
215#ifndef DYNAMIC_LINK
216 err_setstr(ImportError, "dynamically linked modules not supported");
217 return NULL;
218#else
219 object *m;
220 char funcname[258];
221 dl_funcptr p = NULL;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000222#ifdef USE_SHLIB
223 static struct {
224 dev_t dev;
225 ino_t ino;
226 void *handle;
227 } handles[128];
228 static int nhandles = 0;
229#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000230 sprintf(funcname, FUNCNAME_PATTERN, name);
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000231#ifdef USE_SHLIB
232 if (fp != NULL) {
233 int i;
234 struct stat statb;
235 fstat(fileno(fp), &statb);
236 for (i = 0; i < nhandles; i++) {
237 if (statb.st_dev == handles[i].dev &&
238 statb.st_ino == handles[i].ino) {
239 p = (dl_funcptr) dlsym(handles[i].handle,
240 funcname);
241 goto got_it;
242 }
243 }
244 if (nhandles < 128) {
245 handles[nhandles].dev = statb.st_dev;
246 handles[nhandles].ino = statb.st_ino;
247 }
248 }
249#endif /* USE_SHLIB */
Jack Jansen5d9acb61995-06-14 14:54:25 +0000250#ifdef USE_MAC_DYNAMIC_LOADING
251 /*
252 ** Dynamic loading of CFM shared libraries on the Mac.
253 ** The code has become more convoluted than it was, because we want to be able
254 ** to put multiple modules in a single file. For this reason, we have to determine
255 ** the fragment name, and we cannot use the library entry point but we have to locate
256 ** the correct init routine "by hand".
257 */
Jack Jansen4e043731995-02-13 22:42:34 +0000258 {
259 FSSpec libspec;
260 CFragConnectionID connID;
Guido van Rossum6a75d261995-02-18 14:51:15 +0000261 Ptr mainAddr;
262 Str255 errMessage;
263 OSErr err;
Jack Jansen5d9acb61995-06-14 14:54:25 +0000264 Boolean isfolder, didsomething;
265 char buf[512];
266 Str63 fragname;
267 Ptr symAddr;
268 CFragSymbolClass class;
Jack Jansen4e043731995-02-13 22:42:34 +0000269
Jack Jansen5d9acb61995-06-14 14:54:25 +0000270 /* First resolve any aliases to find the real file */
Jack Jansen4e043731995-02-13 22:42:34 +0000271 (void)FSMakeFSSpec(0, 0, Pstring(pathname), &libspec);
Jack Jansen5d9acb61995-06-14 14:54:25 +0000272 err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
273 if ( err ) {
274 sprintf(buf, "%s: %s", pathname, PyMac_StrError(err));
275 err_setstr(ImportError, buf);
276 return NULL;
277 }
278 /* Next, determine the fragment name, by stripping '.slb' and 'module' */
279 memcpy(fragname+1, libspec.name+1, libspec.name[0]);
280 fragname[0] = libspec.name[0];
281 if( strncmp((char *)(fragname+1+fragname[0]-4), ".slb", 4) == 0 )
282 fragname[0] -= 4;
283 if ( strncmp((char *)(fragname+1+fragname[0]-6), "module", 6) == 0 )
284 fragname[0] -= 6;
285 /* Load the fragment (or return the connID if it is already loaded */
286 err = GetDiskFragment(&libspec, 0, 0, fragname,
Guido van Rossum6a75d261995-02-18 14:51:15 +0000287 kLoadCFrag, &connID, &mainAddr,
288 errMessage);
Jack Jansen4e043731995-02-13 22:42:34 +0000289 if ( err ) {
Guido van Rossum3097c3a1995-02-21 21:02:46 +0000290 sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err));
Jack Jansen4e043731995-02-13 22:42:34 +0000291 err_setstr(ImportError, buf);
292 return NULL;
293 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000294 /* Locate the address of the correct init function */
295 err = FindSymbol(connID, Pstring(funcname), &symAddr, &class);
296 if ( err ) {
297 sprintf(buf, "%s: %s", funcname, PyMac_StrError(err));
298 err_setstr(ImportError, buf);
299 return NULL;
300 }
301 p = (dl_funcptr)symAddr;
Jack Jansen4e043731995-02-13 22:42:34 +0000302 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000303#endif /* USE_MAC_DYNAMIC_LOADING */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000304#ifdef USE_SHLIB
305 {
306#ifdef RTLD_NOW
307 /* RTLD_NOW: resolve externals now
308 (i.e. core dump now if some are missing) */
309 void *handle = dlopen(pathname, RTLD_NOW);
310#else
311 void *handle;
312 if (verbose)
313 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
314 handle = dlopen(pathname, RTLD_LAZY);
315#endif /* RTLD_NOW */
316 if (handle == NULL) {
317 err_setstr(ImportError, dlerror());
318 return NULL;
319 }
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000320 if (fp != NULL && nhandles < 128)
321 handles[nhandles++].handle = handle;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000322 p = (dl_funcptr) dlsym(handle, funcname);
323 }
324#endif /* USE_SHLIB */
325#ifdef _AIX
326 p = (dl_funcptr) load(pathname, 1, 0);
327 if (p == NULL) {
328 aix_loaderror(pathname);
329 return NULL;
330 }
331#endif /* _AIX */
332#ifdef NT
333 {
334 HINSTANCE hDLL;
335 hDLL = LoadLibrary(pathname);
336 if (hDLL==NULL){
Guido van Rossum11a3f0c21995-07-18 14:40:09 +0000337 char errBuf[256];
338 unsigned int errorCode;
339
340 /* Get an error string from Win32 error code */
341 char theInfo[256]; /* Pointer to error text from system */
342 int theLength; /* Length of error text */
343
344 errorCode = GetLastError();
345
346 theLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, /* flags */
347 NULL, /* message source */
348 errorCode, /* the message (error) ID */
349 0, /* default language environment */
350 (LPTSTR) theInfo, /* the buffer */
351 sizeof(theInfo), /* the buffer size */
352 NULL); /* no additional format args. */
353
354 /* Problem: could not get the error message. This should not happen if called correctly. */
355 if (theLength == 0) {
356 sprintf(errBuf, "DLL load failed with error code %d", errorCode);
357 } else {
358 int len;
359 /* For some reason a \r\n is appended to the text */
360 if (theLength >= 2 && theInfo[theLength-2] == '\r' && theInfo[theLength-1] == '\n') {
361 theLength -= 2;
362 theInfo[theLength] = '\0';
363 }
364 strcpy(errBuf, "DLL load failed: ");
365 len = strlen(errBuf);
366 strncpy(errBuf+len, theInfo, sizeof(errBuf)-len);
367 errBuf[sizeof(errBuf)-1] = '\0';
368 }
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000369 err_setstr(ImportError, errBuf);
370 return NULL;
371 }
372 p = GetProcAddress(hDLL, funcname);
373 }
374#endif /* NT */
375#ifdef USE_DL
376 p = dl_loadmod(getprogramname(), pathname, funcname);
377#endif /* USE_DL */
378#ifdef USE_RLD
379 {
380 NXStream *errorStream;
381 struct mach_header *new_header;
382 const char *filenames[2];
383 long ret;
384 unsigned long ptr;
385
386 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
387 filenames[0] = pathname;
388 filenames[1] = NULL;
389 ret = rld_load(errorStream, &new_header,
390 filenames, NULL);
391
392 /* extract the error messages for the exception */
393 if(!ret) {
394 char *streamBuf;
395 int len, maxLen;
396
397 NXPutc(errorStream, (char)0);
398
399 NXGetMemoryBuffer(errorStream,
400 &streamBuf, &len, &maxLen);
401 err_setstr(ImportError, streamBuf);
402 }
403
404 if(ret && rld_lookup(errorStream, funcname, &ptr))
405 p = (dl_funcptr) ptr;
406
407 NXCloseMemory(errorStream, NX_FREEBUFFER);
408
409 if(!ret)
410 return NULL;
411 }
412#endif /* USE_RLD */
413#ifdef hpux
414 {
415 shl_t lib;
416 int flags;
417
418 flags = BIND_DEFERRED;
419 if (verbose)
420 {
421 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
422 printf("shl_load %s\n",pathname);
423 }
424 lib = shl_load(pathname, flags, 0);
425 if (lib == NULL)
426 {
427 char buf[256];
428 if (verbose)
429 perror(pathname);
430 sprintf(buf, "Failed to load %.200s", pathname);
431 err_setstr(ImportError, buf);
432 return NULL;
433 }
434 if (verbose)
435 printf("shl_findsym %s\n", funcname);
436 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
437 if (p == NULL && verbose)
438 perror(funcname);
439 }
440#endif /* hpux */
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000441 got_it:
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000442 if (p == NULL) {
443 err_setstr(ImportError,
444 "dynamic module does not define init function");
445 return NULL;
446 }
447 (*p)();
448
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000449 m = dictlookup(import_modules, name);
450 if (m == NULL) {
451 if (err_occurred() == NULL)
452 err_setstr(SystemError,
453 "dynamic module not initialized properly");
454 return NULL;
455 }
456 if (verbose)
457 fprintf(stderr,
458 "import %s # dynamically loaded from %s\n",
459 name, pathname);
460 INCREF(m);
461 return m;
462#endif /* DYNAMIC_LINK */
463}
464
465
466#ifdef _AIX
467
468#include <ctype.h> /* for isdigit() */
469#include <errno.h> /* for global errno */
470#include <string.h> /* for strerror() */
471
472void aix_loaderror(char *pathname)
473{
474
475 char *message[8], errbuf[1024];
476 int i,j;
477
478 struct errtab {
479 int errno;
480 char *errstr;
481 } load_errtab[] = {
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000482 {L_ERROR_TOOMANY, "too many errors, rest skipped."},
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000483 {L_ERROR_NOLIB, "can't load library:"},
484 {L_ERROR_UNDEF, "can't find symbol in library:"},
485 {L_ERROR_RLDBAD,
486 "RLD index out of range or bad relocation type:"},
487 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
488 {L_ERROR_MEMBER,
489 "file not an archive or does not contain requested member:"},
490 {L_ERROR_TYPE, "symbol table mismatch:"},
491 {L_ERROR_ALIGN, "text allignment in file is wrong."},
492 {L_ERROR_SYSTEM, "System error:"},
493 {L_ERROR_ERRNO, NULL}
494 };
495
496#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
497#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
498
499 sprintf(errbuf, " from module %.200s ", pathname);
500
501 if (!loadquery(1, &message[0], sizeof(message)))
502 ERRBUF_APPEND(strerror(errno));
503 for(i = 0; message[i] && *message[i]; i++) {
504 int nerr = atoi(message[i]);
505 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
506 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
507 ERRBUF_APPEND(load_errtab[i].errstr);
508 }
509 while (isdigit(*message[i])) message[i]++ ;
510 ERRBUF_APPEND(message[i]);
511 ERRBUF_APPEND("\n");
512 }
513 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
514 err_setstr(ImportError, errbuf);
515 return;
516}
517
518#endif /* _AIX */