blob: 16b50aff0cea8ee26020fdc0551b721deea8fb35 [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 Jansen4e043731995-02-13 22:42:34 +0000153#include <CodeFragments.h>
Jack Janseneceb3e31995-06-27 13:15:15 +0000154#ifdef SYMANTEC__CFM68K__ /* Really just an older version of Universal Headers */
Guido van Rossum6a75d261995-02-18 14:51:15 +0000155#define CFragConnectionID ConnectionID
156#define kLoadCFrag 0x01
157#endif
Jack Jansen4e043731995-02-13 22:42:34 +0000158#include <Files.h>
159#include "macdefs.h"
160#include "macglue.h"
161#endif
162
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000163#ifdef USE_RLD
164#include <mach-o/rld.h>
165#define FUNCNAME_PATTERN "_init%.200s"
166#ifndef _DL_FUNCPTR_DEFINED
167typedef void (*dl_funcptr)();
168#endif
169#endif /* USE_RLD */
170
171extern char *getprogramname();
172
173#ifndef FUNCNAME_PATTERN
Guido van Rossum0fbec641995-02-27 10:15:36 +0000174#if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000175#define FUNCNAME_PATTERN "_init%.200s"
176#else
177#define FUNCNAME_PATTERN "init%.200s"
178#endif
179#endif
180
181#if !defined(SHORT_EXT) && !defined(LONG_EXT)
182#define SHORT_EXT ".o"
183#define LONG_EXT "module.o"
184#endif /* !SHORT_EXT && !LONG_EXT */
185
186#endif /* DYNAMIC_LINK */
187
Guido van Rossum6a75d261995-02-18 14:51:15 +0000188/* Max length of module suffix searched for -- accommodates "module.slb" */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000189#ifndef MAXSUFFIXSIZE
Jack Jansen4e043731995-02-13 22:42:34 +0000190#define MAXSUFFIXSIZE 12
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000191#endif
192
193/* Pass it on to import.c */
194int import_maxsuffixsize = MAXSUFFIXSIZE;
195
196struct filedescr import_filetab[] = {
197#ifdef SHORT_EXT
198 {SHORT_EXT, "rb", C_EXTENSION},
199#endif /* !SHORT_EXT */
200#ifdef LONG_EXT
201 {LONG_EXT, "rb", C_EXTENSION},
202#endif /* !LONG_EXT */
203 {".py", "r", PY_SOURCE},
204 {".pyc", "rb", PY_COMPILED},
205 {0, 0}
206};
207
208object *
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000209load_dynamic_module(name, pathname, fp)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000210 char *name;
211 char *pathname;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000212 FILE *fp;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000213{
214#ifndef DYNAMIC_LINK
215 err_setstr(ImportError, "dynamically linked modules not supported");
216 return NULL;
217#else
218 object *m;
219 char funcname[258];
220 dl_funcptr p = NULL;
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000221#ifdef USE_SHLIB
222 static struct {
223 dev_t dev;
224 ino_t ino;
225 void *handle;
226 } handles[128];
227 static int nhandles = 0;
228#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000229 sprintf(funcname, FUNCNAME_PATTERN, name);
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000230#ifdef USE_SHLIB
231 if (fp != NULL) {
232 int i;
233 struct stat statb;
234 fstat(fileno(fp), &statb);
235 for (i = 0; i < nhandles; i++) {
236 if (statb.st_dev == handles[i].dev &&
237 statb.st_ino == handles[i].ino) {
238 p = (dl_funcptr) dlsym(handles[i].handle,
239 funcname);
240 goto got_it;
241 }
242 }
243 if (nhandles < 128) {
244 handles[nhandles].dev = statb.st_dev;
245 handles[nhandles].ino = statb.st_ino;
246 }
247 }
248#endif /* USE_SHLIB */
Jack Jansen5d9acb61995-06-14 14:54:25 +0000249#ifdef USE_MAC_DYNAMIC_LOADING
250 /*
251 ** Dynamic loading of CFM shared libraries on the Mac.
252 ** The code has become more convoluted than it was, because we want to be able
253 ** to put multiple modules in a single file. For this reason, we have to determine
254 ** the fragment name, and we cannot use the library entry point but we have to locate
255 ** the correct init routine "by hand".
256 */
Jack Jansen4e043731995-02-13 22:42:34 +0000257 {
258 FSSpec libspec;
259 CFragConnectionID connID;
Guido van Rossum6a75d261995-02-18 14:51:15 +0000260 Ptr mainAddr;
261 Str255 errMessage;
262 OSErr err;
Jack Jansen5d9acb61995-06-14 14:54:25 +0000263 Boolean isfolder, didsomething;
264 char buf[512];
265 Str63 fragname;
266 Ptr symAddr;
267 CFragSymbolClass class;
Jack Jansen4e043731995-02-13 22:42:34 +0000268
Jack Jansen5d9acb61995-06-14 14:54:25 +0000269 /* First resolve any aliases to find the real file */
Jack Jansen4e043731995-02-13 22:42:34 +0000270 (void)FSMakeFSSpec(0, 0, Pstring(pathname), &libspec);
Jack Janseneceb3e31995-06-27 13:15:15 +0000271#if !(defined(__MWERKS__) && defined(__CFM68K__))
272 /* Bug: not in library */
Jack Jansen5d9acb61995-06-14 14:54:25 +0000273 err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
Jack Janseneceb3e31995-06-27 13:15:15 +0000274#endif
Jack Jansen5d9acb61995-06-14 14:54:25 +0000275 if ( err ) {
276 sprintf(buf, "%s: %s", pathname, PyMac_StrError(err));
277 err_setstr(ImportError, buf);
278 return NULL;
279 }
280 /* Next, determine the fragment name, by stripping '.slb' and 'module' */
281 memcpy(fragname+1, libspec.name+1, libspec.name[0]);
282 fragname[0] = libspec.name[0];
283 if( strncmp((char *)(fragname+1+fragname[0]-4), ".slb", 4) == 0 )
284 fragname[0] -= 4;
285 if ( strncmp((char *)(fragname+1+fragname[0]-6), "module", 6) == 0 )
286 fragname[0] -= 6;
287 /* Load the fragment (or return the connID if it is already loaded */
288 err = GetDiskFragment(&libspec, 0, 0, fragname,
Guido van Rossum6a75d261995-02-18 14:51:15 +0000289 kLoadCFrag, &connID, &mainAddr,
290 errMessage);
Jack Jansen4e043731995-02-13 22:42:34 +0000291 if ( err ) {
Guido van Rossum3097c3a1995-02-21 21:02:46 +0000292 sprintf(buf, "%.*s: %s", errMessage[0], errMessage+1, PyMac_StrError(err));
Jack Jansen4e043731995-02-13 22:42:34 +0000293 err_setstr(ImportError, buf);
294 return NULL;
295 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000296 /* Locate the address of the correct init function */
297 err = FindSymbol(connID, Pstring(funcname), &symAddr, &class);
298 if ( err ) {
299 sprintf(buf, "%s: %s", funcname, PyMac_StrError(err));
300 err_setstr(ImportError, buf);
301 return NULL;
302 }
303 p = (dl_funcptr)symAddr;
Jack Jansen4e043731995-02-13 22:42:34 +0000304 }
Jack Jansen5d9acb61995-06-14 14:54:25 +0000305#endif /* USE_MAC_DYNAMIC_LOADING */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000306#ifdef USE_SHLIB
307 {
308#ifdef RTLD_NOW
309 /* RTLD_NOW: resolve externals now
310 (i.e. core dump now if some are missing) */
311 void *handle = dlopen(pathname, RTLD_NOW);
312#else
313 void *handle;
314 if (verbose)
315 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
316 handle = dlopen(pathname, RTLD_LAZY);
317#endif /* RTLD_NOW */
318 if (handle == NULL) {
319 err_setstr(ImportError, dlerror());
320 return NULL;
321 }
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000322 if (fp != NULL && nhandles < 128)
323 handles[nhandles++].handle = handle;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000324 p = (dl_funcptr) dlsym(handle, funcname);
325 }
326#endif /* USE_SHLIB */
327#ifdef _AIX
328 p = (dl_funcptr) load(pathname, 1, 0);
329 if (p == NULL) {
330 aix_loaderror(pathname);
331 return NULL;
332 }
333#endif /* _AIX */
334#ifdef NT
335 {
336 HINSTANCE hDLL;
337 hDLL = LoadLibrary(pathname);
338 if (hDLL==NULL){
339 char errBuf[64];
340 sprintf(errBuf, "DLL load failed with error code %d",
341 GetLastError());
342 err_setstr(ImportError, errBuf);
343 return NULL;
344 }
345 p = GetProcAddress(hDLL, funcname);
346 }
347#endif /* NT */
348#ifdef USE_DL
349 p = dl_loadmod(getprogramname(), pathname, funcname);
350#endif /* USE_DL */
351#ifdef USE_RLD
352 {
353 NXStream *errorStream;
354 struct mach_header *new_header;
355 const char *filenames[2];
356 long ret;
357 unsigned long ptr;
358
359 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
360 filenames[0] = pathname;
361 filenames[1] = NULL;
362 ret = rld_load(errorStream, &new_header,
363 filenames, NULL);
364
365 /* extract the error messages for the exception */
366 if(!ret) {
367 char *streamBuf;
368 int len, maxLen;
369
370 NXPutc(errorStream, (char)0);
371
372 NXGetMemoryBuffer(errorStream,
373 &streamBuf, &len, &maxLen);
374 err_setstr(ImportError, streamBuf);
375 }
376
377 if(ret && rld_lookup(errorStream, funcname, &ptr))
378 p = (dl_funcptr) ptr;
379
380 NXCloseMemory(errorStream, NX_FREEBUFFER);
381
382 if(!ret)
383 return NULL;
384 }
385#endif /* USE_RLD */
386#ifdef hpux
387 {
388 shl_t lib;
389 int flags;
390
391 flags = BIND_DEFERRED;
392 if (verbose)
393 {
394 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
395 printf("shl_load %s\n",pathname);
396 }
397 lib = shl_load(pathname, flags, 0);
398 if (lib == NULL)
399 {
400 char buf[256];
401 if (verbose)
402 perror(pathname);
403 sprintf(buf, "Failed to load %.200s", pathname);
404 err_setstr(ImportError, buf);
405 return NULL;
406 }
407 if (verbose)
408 printf("shl_findsym %s\n", funcname);
409 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
410 if (p == NULL && verbose)
411 perror(funcname);
412 }
413#endif /* hpux */
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000414 got_it:
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000415 if (p == NULL) {
416 err_setstr(ImportError,
417 "dynamic module does not define init function");
418 return NULL;
419 }
420 (*p)();
421
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000422 m = dictlookup(import_modules, name);
423 if (m == NULL) {
424 if (err_occurred() == NULL)
425 err_setstr(SystemError,
426 "dynamic module not initialized properly");
427 return NULL;
428 }
429 if (verbose)
430 fprintf(stderr,
431 "import %s # dynamically loaded from %s\n",
432 name, pathname);
433 INCREF(m);
434 return m;
435#endif /* DYNAMIC_LINK */
436}
437
438
439#ifdef _AIX
440
441#include <ctype.h> /* for isdigit() */
442#include <errno.h> /* for global errno */
443#include <string.h> /* for strerror() */
444
445void aix_loaderror(char *pathname)
446{
447
448 char *message[8], errbuf[1024];
449 int i,j;
450
451 struct errtab {
452 int errno;
453 char *errstr;
454 } load_errtab[] = {
Sjoerd Mullenderfbe6d331995-06-12 15:51:34 +0000455 {L_ERROR_TOOMANY, "too many errors, rest skipped."},
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000456 {L_ERROR_NOLIB, "can't load library:"},
457 {L_ERROR_UNDEF, "can't find symbol in library:"},
458 {L_ERROR_RLDBAD,
459 "RLD index out of range or bad relocation type:"},
460 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
461 {L_ERROR_MEMBER,
462 "file not an archive or does not contain requested member:"},
463 {L_ERROR_TYPE, "symbol table mismatch:"},
464 {L_ERROR_ALIGN, "text allignment in file is wrong."},
465 {L_ERROR_SYSTEM, "System error:"},
466 {L_ERROR_ERRNO, NULL}
467 };
468
469#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
470#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
471
472 sprintf(errbuf, " from module %.200s ", pathname);
473
474 if (!loadquery(1, &message[0], sizeof(message)))
475 ERRBUF_APPEND(strerror(errno));
476 for(i = 0; message[i] && *message[i]; i++) {
477 int nerr = atoi(message[i]);
478 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
479 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
480 ERRBUF_APPEND(load_errtab[i].errstr);
481 }
482 while (isdigit(*message[i])) message[i]++ ;
483 ERRBUF_APPEND(message[i]);
484 ERRBUF_APPEND("\n");
485 }
486 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
487 err_setstr(ImportError, errbuf);
488 return;
489}
490
491#endif /* _AIX */