blob: 882402cf89f5896831e991cd338da0a78a34f24e [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 Rossum46c76a61995-01-20 16:53:54 +000039 USE_RLD -- NeXT dynamic linking (currently disabled)
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
45 WITH_MAC_DL -- Mac dynamic linking (highly experimental)
Jack Jansen4e043731995-02-13 22:42:34 +000046 USE_MAC_SHARED_LIBRARY -- Another mac dynamic linking method
Guido van Rossum1ae940a1995-01-02 19:04:15 +000047 SHORT_EXT -- short extension for dynamic module, e.g. ".so"
48 LONG_EXT -- long extension, e.g. "module.so"
49 hpux -- HP-UX Dynamic Linking - defined by the compiler
Guido van Rossum46c76a61995-01-20 16:53:54 +000050 __NetBSD__ -- NetBSD shared libraries (not quite SVR4 compatible)
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
58#ifdef hpux
59#define DYNAMIC_LINK
60#include <errno.h>
61typedef void (*dl_funcptr)();
62#define _DL_FUNCPTR_DEFINED 1
63#define SHORT_EXT ".sl"
64#define LONG_EXT "module.sl"
65#endif
66
Guido van Rossum46c76a61995-01-20 16:53:54 +000067#ifdef __NetBSD__
68#define DYNAMIC_LINK
69#define USE_SHLIB
70
71#define dlerror() "error in dynamic linking"
72#endif
73
Guido van Rossum1ae940a1995-01-02 19:04:15 +000074#ifdef NT
75#define DYNAMIC_LINK
76#include <windows.h>
77typedef FARPROC dl_funcptr;
78#define _DL_FUNCPTR_DEFINED
Guido van Rossum5fb1da71995-01-07 12:36:02 +000079#define SHORT_EXT ".pyd"
80#define LONG_EXT "module.pyd"
Guido van Rossum1ae940a1995-01-02 19:04:15 +000081#endif
82
Guido van Rossum46c76a61995-01-20 16:53:54 +000083#ifdef WITH_RLD
Guido van Rossum1ae940a1995-01-02 19:04:15 +000084#define DYNAMIC_LINK
85#define USE_RLD
86#endif
87
88#ifdef WITH_SGI_DL
89#define DYNAMIC_LINK
90#define USE_DL
91#endif
92
93#ifdef WITH_DL_DLD
94#define DYNAMIC_LINK
95#define USE_DL
96#endif
97
98#ifdef WITH_MAC_DL
99#define DYNAMIC_LINK
100#endif
101
Jack Jansen4e043731995-02-13 22:42:34 +0000102#ifdef USE_MAC_SHARED_LIBRARY
103#define DYNAMIC_LINK
104#define SHORT_EXT ".shlb"
105#define LONG_EXT "module.shlb"
106#ifndef _DL_FUNCPTR_DEFINED
107typedef void (*dl_funcptr)();
108#endif
109#endif
110
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000111#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
112#define DYNAMIC_LINK
113#define USE_SHLIB
114#endif
115
116#ifdef _AIX
117#define DYNAMIC_LINK
118#include <sys/ldr.h>
119typedef void (*dl_funcptr)();
120#define _DL_FUNCPTR_DEFINED
121static void aix_loaderror(char *name);
122#endif
123
124#ifdef DYNAMIC_LINK
125
126#ifdef USE_SHLIB
Guido van Rossum46c76a61995-01-20 16:53:54 +0000127#ifdef __NetBSD__
128#include <nlist.h>
129#include <link.h>
130#else
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000131#include <dlfcn.h>
Guido van Rossum46c76a61995-01-20 16:53:54 +0000132#endif
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000133#ifndef _DL_FUNCPTR_DEFINED
134typedef void (*dl_funcptr)();
135#endif
136#ifndef RTLD_LAZY
137#define RTLD_LAZY 1
138#endif
139#define SHORT_EXT ".so"
140#define LONG_EXT "module.so"
141#endif /* USE_SHLIB */
142
143#if defined(USE_DL) || defined(hpux)
144#include "dl.h"
145#endif
146
147#ifdef WITH_MAC_DL
148#include "dynamic_load.h"
149#endif
150
Jack Jansen4e043731995-02-13 22:42:34 +0000151#ifdef USE_MAC_SHARED_LIBRARY
152#include <CodeFragments.h>
153#include <Files.h>
154#include "macdefs.h"
155#include "macglue.h"
156#endif
157
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000158#ifdef USE_RLD
159#include <mach-o/rld.h>
160#define FUNCNAME_PATTERN "_init%.200s"
161#ifndef _DL_FUNCPTR_DEFINED
162typedef void (*dl_funcptr)();
163#endif
164#endif /* USE_RLD */
165
166extern char *getprogramname();
167
168#ifndef FUNCNAME_PATTERN
Guido van Rossum46c76a61995-01-20 16:53:54 +0000169#if defined(__hp9000s300) || defined(__NetBSD__)
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000170#define FUNCNAME_PATTERN "_init%.200s"
171#else
172#define FUNCNAME_PATTERN "init%.200s"
173#endif
174#endif
175
176#if !defined(SHORT_EXT) && !defined(LONG_EXT)
177#define SHORT_EXT ".o"
178#define LONG_EXT "module.o"
179#endif /* !SHORT_EXT && !LONG_EXT */
180
181#endif /* DYNAMIC_LINK */
182
Jack Jansen4e043731995-02-13 22:42:34 +0000183/* Max length of module suffix searched for -- accommodates "module.shlb" */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000184#ifndef MAXSUFFIXSIZE
Jack Jansen4e043731995-02-13 22:42:34 +0000185#define MAXSUFFIXSIZE 12
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000186#endif
187
188/* Pass it on to import.c */
189int import_maxsuffixsize = MAXSUFFIXSIZE;
190
191struct filedescr import_filetab[] = {
192#ifdef SHORT_EXT
193 {SHORT_EXT, "rb", C_EXTENSION},
194#endif /* !SHORT_EXT */
195#ifdef LONG_EXT
196 {LONG_EXT, "rb", C_EXTENSION},
197#endif /* !LONG_EXT */
198 {".py", "r", PY_SOURCE},
199 {".pyc", "rb", PY_COMPILED},
200 {0, 0}
201};
202
203object *
204load_dynamic_module(name, pathname)
205 char *name;
206 char *pathname;
207{
208#ifndef DYNAMIC_LINK
209 err_setstr(ImportError, "dynamically linked modules not supported");
210 return NULL;
211#else
212 object *m;
213 char funcname[258];
214 dl_funcptr p = NULL;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000215 sprintf(funcname, FUNCNAME_PATTERN, name);
216#ifdef WITH_MAC_DL
217 {
218 object *v = dynamic_load(pathname);
219 if (v == NULL)
220 return NULL;
221 }
222#else /* !WITH_MAC_DL */
Jack Jansen4e043731995-02-13 22:42:34 +0000223#ifdef USE_MAC_SHARED_LIBRARY
224 /* Another way to do dynloading on the mac, use CFM */
225 {
226 FSSpec libspec;
227 CFragConnectionID connID;
228 Ptr mainAddr;
229 Str255 errMessage;
230 OSErr err;
231
232 (void)FSMakeFSSpec(0, 0, Pstring(pathname), &libspec);
233 err = GetDiskFragment(&libspec, 0, 0, Pstring(name), kLoadCFrag, &connID, &mainAddr,
234 errMessage);
235 if ( err ) {
236 char buf[512];
237
238 sprintf(buf, "%#s: %s", errMessage, macstrerror(err));
239 err_setstr(ImportError, buf);
240 return NULL;
241 }
242 p = (dl_funcptr)mainAddr;
243 }
244#endif /* USE_MAC_SHARED_LIBRARY */
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000245#ifdef USE_SHLIB
246 {
247#ifdef RTLD_NOW
248 /* RTLD_NOW: resolve externals now
249 (i.e. core dump now if some are missing) */
250 void *handle = dlopen(pathname, RTLD_NOW);
251#else
252 void *handle;
253 if (verbose)
254 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
255 handle = dlopen(pathname, RTLD_LAZY);
256#endif /* RTLD_NOW */
257 if (handle == NULL) {
258 err_setstr(ImportError, dlerror());
259 return NULL;
260 }
261 p = (dl_funcptr) dlsym(handle, funcname);
262 }
263#endif /* USE_SHLIB */
264#ifdef _AIX
265 p = (dl_funcptr) load(pathname, 1, 0);
266 if (p == NULL) {
267 aix_loaderror(pathname);
268 return NULL;
269 }
270#endif /* _AIX */
271#ifdef NT
272 {
273 HINSTANCE hDLL;
274 hDLL = LoadLibrary(pathname);
275 if (hDLL==NULL){
276 char errBuf[64];
277 sprintf(errBuf, "DLL load failed with error code %d",
278 GetLastError());
279 err_setstr(ImportError, errBuf);
280 return NULL;
281 }
282 p = GetProcAddress(hDLL, funcname);
283 }
284#endif /* NT */
285#ifdef USE_DL
286 p = dl_loadmod(getprogramname(), pathname, funcname);
287#endif /* USE_DL */
288#ifdef USE_RLD
289 {
290 NXStream *errorStream;
291 struct mach_header *new_header;
292 const char *filenames[2];
293 long ret;
294 unsigned long ptr;
295
296 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
297 filenames[0] = pathname;
298 filenames[1] = NULL;
299 ret = rld_load(errorStream, &new_header,
300 filenames, NULL);
301
302 /* extract the error messages for the exception */
303 if(!ret) {
304 char *streamBuf;
305 int len, maxLen;
306
307 NXPutc(errorStream, (char)0);
308
309 NXGetMemoryBuffer(errorStream,
310 &streamBuf, &len, &maxLen);
311 err_setstr(ImportError, streamBuf);
312 }
313
314 if(ret && rld_lookup(errorStream, funcname, &ptr))
315 p = (dl_funcptr) ptr;
316
317 NXCloseMemory(errorStream, NX_FREEBUFFER);
318
319 if(!ret)
320 return NULL;
321 }
322#endif /* USE_RLD */
323#ifdef hpux
324 {
325 shl_t lib;
326 int flags;
327
328 flags = BIND_DEFERRED;
329 if (verbose)
330 {
331 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
332 printf("shl_load %s\n",pathname);
333 }
334 lib = shl_load(pathname, flags, 0);
335 if (lib == NULL)
336 {
337 char buf[256];
338 if (verbose)
339 perror(pathname);
340 sprintf(buf, "Failed to load %.200s", pathname);
341 err_setstr(ImportError, buf);
342 return NULL;
343 }
344 if (verbose)
345 printf("shl_findsym %s\n", funcname);
346 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
347 if (p == NULL && verbose)
348 perror(funcname);
349 }
350#endif /* hpux */
351 if (p == NULL) {
352 err_setstr(ImportError,
353 "dynamic module does not define init function");
354 return NULL;
355 }
356 (*p)();
357
358#endif /* !WITH_MAC_DL */
359 m = dictlookup(import_modules, name);
360 if (m == NULL) {
361 if (err_occurred() == NULL)
362 err_setstr(SystemError,
363 "dynamic module not initialized properly");
364 return NULL;
365 }
366 if (verbose)
367 fprintf(stderr,
368 "import %s # dynamically loaded from %s\n",
369 name, pathname);
370 INCREF(m);
371 return m;
372#endif /* DYNAMIC_LINK */
373}
374
375
376#ifdef _AIX
377
378#include <ctype.h> /* for isdigit() */
379#include <errno.h> /* for global errno */
380#include <string.h> /* for strerror() */
381
382void aix_loaderror(char *pathname)
383{
384
385 char *message[8], errbuf[1024];
386 int i,j;
387
388 struct errtab {
389 int errno;
390 char *errstr;
391 } load_errtab[] = {
392 {L_ERROR_TOOMANY, "to many errors, rest skipped."},
393 {L_ERROR_NOLIB, "can't load library:"},
394 {L_ERROR_UNDEF, "can't find symbol in library:"},
395 {L_ERROR_RLDBAD,
396 "RLD index out of range or bad relocation type:"},
397 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
398 {L_ERROR_MEMBER,
399 "file not an archive or does not contain requested member:"},
400 {L_ERROR_TYPE, "symbol table mismatch:"},
401 {L_ERROR_ALIGN, "text allignment in file is wrong."},
402 {L_ERROR_SYSTEM, "System error:"},
403 {L_ERROR_ERRNO, NULL}
404 };
405
406#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
407#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
408
409 sprintf(errbuf, " from module %.200s ", pathname);
410
411 if (!loadquery(1, &message[0], sizeof(message)))
412 ERRBUF_APPEND(strerror(errno));
413 for(i = 0; message[i] && *message[i]; i++) {
414 int nerr = atoi(message[i]);
415 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
416 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
417 ERRBUF_APPEND(load_errtab[i].errstr);
418 }
419 while (isdigit(*message[i])) message[i]++ ;
420 ERRBUF_APPEND(message[i]);
421 ERRBUF_APPEND("\n");
422 }
423 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
424 err_setstr(ImportError, errbuf);
425 return;
426}
427
428#endif /* _AIX */