blob: f676e3f2df411e5dc46b5905543da994595869db [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
39 USE_RLD -- NeXT dynamic linking
40 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)
46 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
49
50 (The other WITH_* symbols are used only once, to set the
51 appropriate symbols.)
52*/
53
54/* Configure dynamic linking */
55
56#ifdef hpux
57#define DYNAMIC_LINK
58#include <errno.h>
59typedef void (*dl_funcptr)();
60#define _DL_FUNCPTR_DEFINED 1
61#define SHORT_EXT ".sl"
62#define LONG_EXT "module.sl"
63#endif
64
65#ifdef NT
66#define DYNAMIC_LINK
67#include <windows.h>
68typedef FARPROC dl_funcptr;
69#define _DL_FUNCPTR_DEFINED
70#define SHORT_EXT ".dll"
71#define LONG_EXT "module.dll"
72#endif
73
74#if defined(NeXT) || defined(WITH_RLD)
75#define DYNAMIC_LINK
76#define USE_RLD
77#endif
78
79#ifdef WITH_SGI_DL
80#define DYNAMIC_LINK
81#define USE_DL
82#endif
83
84#ifdef WITH_DL_DLD
85#define DYNAMIC_LINK
86#define USE_DL
87#endif
88
89#ifdef WITH_MAC_DL
90#define DYNAMIC_LINK
91#endif
92
93#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
94#define DYNAMIC_LINK
95#define USE_SHLIB
96#endif
97
98#ifdef _AIX
99#define DYNAMIC_LINK
100#include <sys/ldr.h>
101typedef void (*dl_funcptr)();
102#define _DL_FUNCPTR_DEFINED
103static void aix_loaderror(char *name);
104#endif
105
106#ifdef DYNAMIC_LINK
107
108#ifdef USE_SHLIB
109#include <dlfcn.h>
110#ifndef _DL_FUNCPTR_DEFINED
111typedef void (*dl_funcptr)();
112#endif
113#ifndef RTLD_LAZY
114#define RTLD_LAZY 1
115#endif
116#define SHORT_EXT ".so"
117#define LONG_EXT "module.so"
118#endif /* USE_SHLIB */
119
120#if defined(USE_DL) || defined(hpux)
121#include "dl.h"
122#endif
123
124#ifdef WITH_MAC_DL
125#include "dynamic_load.h"
126#endif
127
128#ifdef USE_RLD
129#include <mach-o/rld.h>
130#define FUNCNAME_PATTERN "_init%.200s"
131#ifndef _DL_FUNCPTR_DEFINED
132typedef void (*dl_funcptr)();
133#endif
134#endif /* USE_RLD */
135
136extern char *getprogramname();
137
138#ifndef FUNCNAME_PATTERN
139#if defined(__hp9000s300)
140#define FUNCNAME_PATTERN "_init%.200s"
141#else
142#define FUNCNAME_PATTERN "init%.200s"
143#endif
144#endif
145
146#if !defined(SHORT_EXT) && !defined(LONG_EXT)
147#define SHORT_EXT ".o"
148#define LONG_EXT "module.o"
149#endif /* !SHORT_EXT && !LONG_EXT */
150
151#endif /* DYNAMIC_LINK */
152
153/* Max length of module suffix searched for -- accommodates "module.so" */
154#ifndef MAXSUFFIXSIZE
155#define MAXSUFFIXSIZE 10
156#endif
157
158/* Pass it on to import.c */
159int import_maxsuffixsize = MAXSUFFIXSIZE;
160
161struct filedescr import_filetab[] = {
162#ifdef SHORT_EXT
163 {SHORT_EXT, "rb", C_EXTENSION},
164#endif /* !SHORT_EXT */
165#ifdef LONG_EXT
166 {LONG_EXT, "rb", C_EXTENSION},
167#endif /* !LONG_EXT */
168 {".py", "r", PY_SOURCE},
169 {".pyc", "rb", PY_COMPILED},
170 {0, 0}
171};
172
173object *
174load_dynamic_module(name, pathname)
175 char *name;
176 char *pathname;
177{
178#ifndef DYNAMIC_LINK
179 err_setstr(ImportError, "dynamically linked modules not supported");
180 return NULL;
181#else
182 object *m;
183 char funcname[258];
184 dl_funcptr p = NULL;
185 if (m != NULL) {
186 err_setstr(ImportError,
187 "cannot reload dynamically loaded module");
188 return NULL;
189 }
190 sprintf(funcname, FUNCNAME_PATTERN, name);
191#ifdef WITH_MAC_DL
192 {
193 object *v = dynamic_load(pathname);
194 if (v == NULL)
195 return NULL;
196 }
197#else /* !WITH_MAC_DL */
198#ifdef USE_SHLIB
199 {
200#ifdef RTLD_NOW
201 /* RTLD_NOW: resolve externals now
202 (i.e. core dump now if some are missing) */
203 void *handle = dlopen(pathname, RTLD_NOW);
204#else
205 void *handle;
206 if (verbose)
207 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
208 handle = dlopen(pathname, RTLD_LAZY);
209#endif /* RTLD_NOW */
210 if (handle == NULL) {
211 err_setstr(ImportError, dlerror());
212 return NULL;
213 }
214 p = (dl_funcptr) dlsym(handle, funcname);
215 }
216#endif /* USE_SHLIB */
217#ifdef _AIX
218 p = (dl_funcptr) load(pathname, 1, 0);
219 if (p == NULL) {
220 aix_loaderror(pathname);
221 return NULL;
222 }
223#endif /* _AIX */
224#ifdef NT
225 {
226 HINSTANCE hDLL;
227 hDLL = LoadLibrary(pathname);
228 if (hDLL==NULL){
229 char errBuf[64];
230 sprintf(errBuf, "DLL load failed with error code %d",
231 GetLastError());
232 err_setstr(ImportError, errBuf);
233 return NULL;
234 }
235 p = GetProcAddress(hDLL, funcname);
236 }
237#endif /* NT */
238#ifdef USE_DL
239 p = dl_loadmod(getprogramname(), pathname, funcname);
240#endif /* USE_DL */
241#ifdef USE_RLD
242 {
243 NXStream *errorStream;
244 struct mach_header *new_header;
245 const char *filenames[2];
246 long ret;
247 unsigned long ptr;
248
249 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
250 filenames[0] = pathname;
251 filenames[1] = NULL;
252 ret = rld_load(errorStream, &new_header,
253 filenames, NULL);
254
255 /* extract the error messages for the exception */
256 if(!ret) {
257 char *streamBuf;
258 int len, maxLen;
259
260 NXPutc(errorStream, (char)0);
261
262 NXGetMemoryBuffer(errorStream,
263 &streamBuf, &len, &maxLen);
264 err_setstr(ImportError, streamBuf);
265 }
266
267 if(ret && rld_lookup(errorStream, funcname, &ptr))
268 p = (dl_funcptr) ptr;
269
270 NXCloseMemory(errorStream, NX_FREEBUFFER);
271
272 if(!ret)
273 return NULL;
274 }
275#endif /* USE_RLD */
276#ifdef hpux
277 {
278 shl_t lib;
279 int flags;
280
281 flags = BIND_DEFERRED;
282 if (verbose)
283 {
284 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
285 printf("shl_load %s\n",pathname);
286 }
287 lib = shl_load(pathname, flags, 0);
288 if (lib == NULL)
289 {
290 char buf[256];
291 if (verbose)
292 perror(pathname);
293 sprintf(buf, "Failed to load %.200s", pathname);
294 err_setstr(ImportError, buf);
295 return NULL;
296 }
297 if (verbose)
298 printf("shl_findsym %s\n", funcname);
299 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
300 if (p == NULL && verbose)
301 perror(funcname);
302 }
303#endif /* hpux */
304 if (p == NULL) {
305 err_setstr(ImportError,
306 "dynamic module does not define init function");
307 return NULL;
308 }
309 (*p)();
310
311#endif /* !WITH_MAC_DL */
312 m = dictlookup(import_modules, name);
313 if (m == NULL) {
314 if (err_occurred() == NULL)
315 err_setstr(SystemError,
316 "dynamic module not initialized properly");
317 return NULL;
318 }
319 if (verbose)
320 fprintf(stderr,
321 "import %s # dynamically loaded from %s\n",
322 name, pathname);
323 INCREF(m);
324 return m;
325#endif /* DYNAMIC_LINK */
326}
327
328
329#ifdef _AIX
330
331#include <ctype.h> /* for isdigit() */
332#include <errno.h> /* for global errno */
333#include <string.h> /* for strerror() */
334
335void aix_loaderror(char *pathname)
336{
337
338 char *message[8], errbuf[1024];
339 int i,j;
340
341 struct errtab {
342 int errno;
343 char *errstr;
344 } load_errtab[] = {
345 {L_ERROR_TOOMANY, "to many errors, rest skipped."},
346 {L_ERROR_NOLIB, "can't load library:"},
347 {L_ERROR_UNDEF, "can't find symbol in library:"},
348 {L_ERROR_RLDBAD,
349 "RLD index out of range or bad relocation type:"},
350 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
351 {L_ERROR_MEMBER,
352 "file not an archive or does not contain requested member:"},
353 {L_ERROR_TYPE, "symbol table mismatch:"},
354 {L_ERROR_ALIGN, "text allignment in file is wrong."},
355 {L_ERROR_SYSTEM, "System error:"},
356 {L_ERROR_ERRNO, NULL}
357 };
358
359#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
360#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
361
362 sprintf(errbuf, " from module %.200s ", pathname);
363
364 if (!loadquery(1, &message[0], sizeof(message)))
365 ERRBUF_APPEND(strerror(errno));
366 for(i = 0; message[i] && *message[i]; i++) {
367 int nerr = atoi(message[i]);
368 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
369 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
370 ERRBUF_APPEND(load_errtab[i].errstr);
371 }
372 while (isdigit(*message[i])) message[i]++ ;
373 ERRBUF_APPEND(message[i]);
374 ERRBUF_APPEND("\n");
375 }
376 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
377 err_setstr(ImportError, errbuf);
378 return;
379}
380
381#endif /* _AIX */