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