blob: e802df1a54ae5b1b794525baa2b251708576f6f9 [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
Guido van Rossumff4af061996-01-12 01:17:50 +000057#ifdef __hpux
58#define hpux
59#endif
60
Guido van Rossum1ae940a1995-01-02 19:04:15 +000061#ifdef hpux
62#define DYNAMIC_LINK
63#include <errno.h>
64typedef void (*dl_funcptr)();
65#define _DL_FUNCPTR_DEFINED 1
66#define SHORT_EXT ".sl"
67#define LONG_EXT "module.sl"
68#endif
69
Guido van Rossum46c76a61995-01-20 16:53:54 +000070#ifdef __NetBSD__
71#define DYNAMIC_LINK
72#define USE_SHLIB
73
74#define dlerror() "error in dynamic linking"
75#endif
76
Guido van Rossum0fbec641995-02-27 10:15:36 +000077#ifdef __WIN32__
78#define NT
79#endif
80
Guido van Rossum1ae940a1995-01-02 19:04:15 +000081#ifdef NT
82#define DYNAMIC_LINK
83#include <windows.h>
84typedef FARPROC dl_funcptr;
85#define _DL_FUNCPTR_DEFINED
Guido van Rossum5fb1da71995-01-07 12:36:02 +000086#define SHORT_EXT ".pyd"
87#define LONG_EXT "module.pyd"
Guido van Rossum1ae940a1995-01-02 19:04:15 +000088#endif
89
Guido van Rossum75f288d1995-06-14 22:07:26 +000090#ifdef NeXT
Guido van Rossum1ae940a1995-01-02 19:04:15 +000091#define DYNAMIC_LINK
92#define USE_RLD
93#endif
94
95#ifdef WITH_SGI_DL
96#define DYNAMIC_LINK
97#define USE_DL
98#endif
99
100#ifdef WITH_DL_DLD
101#define DYNAMIC_LINK
102#define USE_DL
103#endif
104
Guido van Rossum6a75d261995-02-18 14:51:15 +0000105#ifdef __CFM68K__
Jack Jansen5d9acb61995-06-14 14:54:25 +0000106#define USE_MAC_DYNAMIC_LOADING
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000107#endif
108
Jack Jansen5d9acb61995-06-14 14:54:25 +0000109#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen4e043731995-02-13 22:42:34 +0000110#define DYNAMIC_LINK
Guido van Rossum6a75d261995-02-18 14:51:15 +0000111#define SHORT_EXT ".slb"
112#define LONG_EXT "module.slb"
Jack Jansen4e043731995-02-13 22:42:34 +0000113#ifndef _DL_FUNCPTR_DEFINED
114typedef void (*dl_funcptr)();
115#endif
116#endif
117
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000118#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
119#define DYNAMIC_LINK
120#define USE_SHLIB
121#endif
122
123#ifdef _AIX
124#define DYNAMIC_LINK
125#include <sys/ldr.h>
126typedef void (*dl_funcptr)();
127#define _DL_FUNCPTR_DEFINED
128static void aix_loaderror(char *name);
129#endif
130
131#ifdef DYNAMIC_LINK
132
133#ifdef USE_SHLIB
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000134#include <sys/types.h>
135#include <sys/stat.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000136#ifdef __NetBSD__
137#include <nlist.h>
138#include <link.h>
139#else
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000140#include <dlfcn.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000141#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000142#ifndef _DL_FUNCPTR_DEFINED
143typedef void (*dl_funcptr)();
144#endif
145#ifndef RTLD_LAZY
146#define RTLD_LAZY 1
147#endif
148#define SHORT_EXT ".so"
149#define LONG_EXT "module.so"
150#endif /* USE_SHLIB */
151
152#if defined(USE_DL) || defined(hpux)
153#include "dl.h"
154#endif
155
Jack Jansen5d9acb61995-06-14 14:54:25 +0000156#ifdef USE_MAC_DYNAMIC_LOADING
Jack Jansen0a72e8d1995-10-23 13:54:01 +0000157#include <Aliases.h>
Jack Jansen4e043731995-02-13 22:42:34 +0000158#include <CodeFragments.h>
Jack Janseneceb3e31995-06-27 13:15:15 +0000159#ifdef SYMANTEC__CFM68K__ /* Really just an older version of Universal Headers */
Guido van Rossum6a75d261995-02-18 14:51:15 +0000160#define CFragConnectionID ConnectionID
161#define kLoadCFrag 0x01
162#endif
Jack Jansen4e043731995-02-13 22:42:34 +0000163#include <Files.h>
164#include "macdefs.h"
165#include "macglue.h"
166#endif
167
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000168#ifdef USE_RLD
169#include <mach-o/rld.h>
170#define FUNCNAME_PATTERN "_init%.200s"
171#ifndef _DL_FUNCPTR_DEFINED
172typedef void (*dl_funcptr)();
173#endif
174#endif /* USE_RLD */
175
176extern char *getprogramname();
177
178#ifndef FUNCNAME_PATTERN
Guido van Rossum0fbec641995-02-27 10:15:36 +0000179#if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000180#define FUNCNAME_PATTERN "_init%.200s"
181#else
182#define FUNCNAME_PATTERN "init%.200s"
183#endif
184#endif
185
186#if !defined(SHORT_EXT) && !defined(LONG_EXT)
187#define SHORT_EXT ".o"
188#define LONG_EXT "module.o"
189#endif /* !SHORT_EXT && !LONG_EXT */
190
191#endif /* DYNAMIC_LINK */
192
Guido van Rossum6a75d261995-02-18 14:51:15 +0000193/* Max length of module suffix searched for -- accommodates "module.slb" */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000194#ifndef MAXSUFFIXSIZE
Jack Jansen4e043731995-02-13 22:42:34 +0000195#define MAXSUFFIXSIZE 12
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000196#endif
197
198/* Pass it on to import.c */
199int import_maxsuffixsize = MAXSUFFIXSIZE;
200
201struct filedescr import_filetab[] = {
202#ifdef SHORT_EXT
203 {SHORT_EXT, "rb", C_EXTENSION},
204#endif /* !SHORT_EXT */
205#ifdef LONG_EXT
206 {LONG_EXT, "rb", C_EXTENSION},
207#endif /* !LONG_EXT */
208 {".py", "r", PY_SOURCE},
209 {".pyc", "rb", PY_COMPILED},
210 {0, 0}
211};
212
213object *
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000214load_dynamic_module(name, pathname, fp)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000215 char *name;
216 char *pathname;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000217 FILE *fp;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000218{
219#ifndef DYNAMIC_LINK
220 err_setstr(ImportError, "dynamically linked modules not supported");
221 return NULL;
222#else
223 object *m;
224 char funcname[258];
225 dl_funcptr p = NULL;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000226#ifdef USE_SHLIB
227 static struct {
228 dev_t dev;
229 ino_t ino;
230 void *handle;
231 } handles[128];
232 static int nhandles = 0;
233#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000234 sprintf(funcname, FUNCNAME_PATTERN, name);
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000235#ifdef USE_SHLIB
236 if (fp != NULL) {
237 int i;
238 struct stat statb;
239 fstat(fileno(fp), &statb);
240 for (i = 0; i < nhandles; i++) {
241 if (statb.st_dev == handles[i].dev &&
242 statb.st_ino == handles[i].ino) {
243 p = (dl_funcptr) dlsym(handles[i].handle,
244 funcname);
245 goto got_it;
246 }
247 }
248 if (nhandles < 128) {
249 handles[nhandles].dev = statb.st_dev;
250 handles[nhandles].ino = statb.st_ino;
251 }
252 }
253#endif /* USE_SHLIB */
Jack Jansen5d9acb61995-06-14 14:54:25 +0000254#ifdef USE_MAC_DYNAMIC_LOADING
255 /*
256 ** Dynamic loading of CFM shared libraries on the Mac.
257 ** The code has become more convoluted than it was, because we want to be able
258 ** to put multiple modules in a single file. For this reason, we have to determine
259 ** the fragment name, and we cannot use the library entry point but we have to locate
260 ** the correct init routine "by hand".
261 */
Jack Jansen4e043731995-02-13 22:42:34 +0000262 {
263 FSSpec libspec;
264 CFragConnectionID connID;
Guido van Rossum6a75d261995-02-18 14:51:15 +0000265 Ptr mainAddr;
266 Str255 errMessage;
267 OSErr err;
Jack Jansen5d9acb61995-06-14 14:54:25 +0000268 Boolean isfolder, didsomething;
269 char buf[512];
270 Str63 fragname;
271 Ptr symAddr;
272 CFragSymbolClass class;
Jack Jansen4e043731995-02-13 22:42:34 +0000273
Jack Jansen5d9acb61995-06-14 14:54:25 +0000274 /* First resolve any aliases to find the real file */
Jack Jansen4e043731995-02-13 22:42:34 +0000275 (void)FSMakeFSSpec(0, 0, Pstring(pathname), &libspec);
Jack Jansen5d9acb61995-06-14 14:54:25 +0000276 err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
277 if ( err ) {
278 sprintf(buf, "%s: %s", pathname, PyMac_StrError(err));
279 err_setstr(ImportError, buf);
280 return NULL;
281 }
282 /* Next, determine the fragment name, by stripping '.slb' and 'module' */
283 memcpy(fragname+1, libspec.name+1, libspec.name[0]);
284 fragname[0] = libspec.name[0];
285 if( strncmp((char *)(fragname+1+fragname[0]-4), ".slb", 4) == 0 )
286 fragname[0] -= 4;
287 if ( strncmp((char *)(fragname+1+fragname[0]-6), "module", 6) == 0 )
288 fragname[0] -= 6;
289 /* Load the fragment (or return the connID if it is already loaded */
290 err = GetDiskFragment(&libspec, 0, 0, fragname,
Guido van Rossum6a75d261995-02-18 14:51:15 +0000291 kLoadCFrag, &connID, &mainAddr,
292 errMessage);
Jack Jansen4e043731995-02-13 22:42:34 +0000293 if ( err ) {
Guido van Rossum3097c3a1995-02-21 21:02:46 +0000294 sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err));
Jack Jansen4e043731995-02-13 22:42:34 +0000295 err_setstr(ImportError, buf);
296 return NULL;
297 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000298 /* Locate the address of the correct init function */
299 err = FindSymbol(connID, Pstring(funcname), &symAddr, &class);
300 if ( err ) {
301 sprintf(buf, "%s: %s", funcname, PyMac_StrError(err));
302 err_setstr(ImportError, buf);
303 return NULL;
304 }
305 p = (dl_funcptr)symAddr;
Jack Jansen4e043731995-02-13 22:42:34 +0000306 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000307#endif /* USE_MAC_DYNAMIC_LOADING */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000308#ifdef USE_SHLIB
309 {
310#ifdef RTLD_NOW
311 /* RTLD_NOW: resolve externals now
312 (i.e. core dump now if some are missing) */
313 void *handle = dlopen(pathname, RTLD_NOW);
314#else
315 void *handle;
316 if (verbose)
317 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
318 handle = dlopen(pathname, RTLD_LAZY);
319#endif /* RTLD_NOW */
320 if (handle == NULL) {
321 err_setstr(ImportError, dlerror());
322 return NULL;
323 }
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000324 if (fp != NULL && nhandles < 128)
325 handles[nhandles++].handle = handle;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000326 p = (dl_funcptr) dlsym(handle, funcname);
327 }
328#endif /* USE_SHLIB */
329#ifdef _AIX
330 p = (dl_funcptr) load(pathname, 1, 0);
331 if (p == NULL) {
332 aix_loaderror(pathname);
333 return NULL;
334 }
335#endif /* _AIX */
336#ifdef NT
337 {
338 HINSTANCE hDLL;
339 hDLL = LoadLibrary(pathname);
340 if (hDLL==NULL){
Guido van Rossum11a3f0c21995-07-18 14:40:09 +0000341 char errBuf[256];
342 unsigned int errorCode;
343
344 /* Get an error string from Win32 error code */
345 char theInfo[256]; /* Pointer to error text from system */
346 int theLength; /* Length of error text */
347
348 errorCode = GetLastError();
349
350 theLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, /* flags */
351 NULL, /* message source */
352 errorCode, /* the message (error) ID */
353 0, /* default language environment */
354 (LPTSTR) theInfo, /* the buffer */
355 sizeof(theInfo), /* the buffer size */
356 NULL); /* no additional format args. */
357
358 /* Problem: could not get the error message. This should not happen if called correctly. */
359 if (theLength == 0) {
360 sprintf(errBuf, "DLL load failed with error code %d", errorCode);
361 } else {
362 int len;
363 /* For some reason a \r\n is appended to the text */
364 if (theLength >= 2 && theInfo[theLength-2] == '\r' && theInfo[theLength-1] == '\n') {
365 theLength -= 2;
366 theInfo[theLength] = '\0';
367 }
368 strcpy(errBuf, "DLL load failed: ");
369 len = strlen(errBuf);
370 strncpy(errBuf+len, theInfo, sizeof(errBuf)-len);
371 errBuf[sizeof(errBuf)-1] = '\0';
372 }
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000373 err_setstr(ImportError, errBuf);
374 return NULL;
375 }
376 p = GetProcAddress(hDLL, funcname);
377 }
378#endif /* NT */
379#ifdef USE_DL
380 p = dl_loadmod(getprogramname(), pathname, funcname);
381#endif /* USE_DL */
382#ifdef USE_RLD
383 {
384 NXStream *errorStream;
385 struct mach_header *new_header;
386 const char *filenames[2];
387 long ret;
388 unsigned long ptr;
389
390 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
391 filenames[0] = pathname;
392 filenames[1] = NULL;
393 ret = rld_load(errorStream, &new_header,
394 filenames, NULL);
395
396 /* extract the error messages for the exception */
397 if(!ret) {
398 char *streamBuf;
399 int len, maxLen;
400
401 NXPutc(errorStream, (char)0);
402
403 NXGetMemoryBuffer(errorStream,
404 &streamBuf, &len, &maxLen);
405 err_setstr(ImportError, streamBuf);
406 }
407
408 if(ret && rld_lookup(errorStream, funcname, &ptr))
409 p = (dl_funcptr) ptr;
410
411 NXCloseMemory(errorStream, NX_FREEBUFFER);
412
413 if(!ret)
414 return NULL;
415 }
416#endif /* USE_RLD */
417#ifdef hpux
418 {
419 shl_t lib;
420 int flags;
421
422 flags = BIND_DEFERRED;
423 if (verbose)
424 {
425 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
426 printf("shl_load %s\n",pathname);
427 }
428 lib = shl_load(pathname, flags, 0);
429 if (lib == NULL)
430 {
431 char buf[256];
432 if (verbose)
433 perror(pathname);
434 sprintf(buf, "Failed to load %.200s", pathname);
435 err_setstr(ImportError, buf);
436 return NULL;
437 }
438 if (verbose)
439 printf("shl_findsym %s\n", funcname);
440 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
441 if (p == NULL && verbose)
442 perror(funcname);
443 }
444#endif /* hpux */
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000445 got_it:
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000446 if (p == NULL) {
447 err_setstr(ImportError,
448 "dynamic module does not define init function");
449 return NULL;
450 }
451 (*p)();
452
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000453 m = dictlookup(import_modules, name);
454 if (m == NULL) {
455 if (err_occurred() == NULL)
456 err_setstr(SystemError,
457 "dynamic module not initialized properly");
458 return NULL;
459 }
460 if (verbose)
461 fprintf(stderr,
462 "import %s # dynamically loaded from %s\n",
463 name, pathname);
464 INCREF(m);
465 return m;
466#endif /* DYNAMIC_LINK */
467}
468
469
470#ifdef _AIX
471
472#include <ctype.h> /* for isdigit() */
473#include <errno.h> /* for global errno */
474#include <string.h> /* for strerror() */
475
476void aix_loaderror(char *pathname)
477{
478
479 char *message[8], errbuf[1024];
480 int i,j;
481
482 struct errtab {
483 int errno;
484 char *errstr;
485 } load_errtab[] = {
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000486 {L_ERROR_TOOMANY, "too many errors, rest skipped."},
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000487 {L_ERROR_NOLIB, "can't load library:"},
488 {L_ERROR_UNDEF, "can't find symbol in library:"},
489 {L_ERROR_RLDBAD,
490 "RLD index out of range or bad relocation type:"},
491 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
492 {L_ERROR_MEMBER,
493 "file not an archive or does not contain requested member:"},
494 {L_ERROR_TYPE, "symbol table mismatch:"},
495 {L_ERROR_ALIGN, "text allignment in file is wrong."},
496 {L_ERROR_SYSTEM, "System error:"},
497 {L_ERROR_ERRNO, NULL}
498 };
499
500#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
501#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
502
503 sprintf(errbuf, " from module %.200s ", pathname);
504
505 if (!loadquery(1, &message[0], sizeof(message)))
506 ERRBUF_APPEND(strerror(errno));
507 for(i = 0; message[i] && *message[i]; i++) {
508 int nerr = atoi(message[i]);
509 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
510 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
511 ERRBUF_APPEND(load_errtab[i].errstr);
512 }
513 while (isdigit(*message[i])) message[i]++ ;
514 ERRBUF_APPEND(message[i]);
515 ERRBUF_APPEND("\n");
516 }
517 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
518 err_setstr(ImportError, errbuf);
519 return;
520}
521
522#endif /* _AIX */