blob: 70b6eb8f75541f2c683598cab74b9b262d83dd0d [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
Guido van Rossum5fb1da71995-01-07 12:36:02 +000070#define SHORT_EXT ".pyd"
71#define LONG_EXT "module.pyd"
Guido van Rossum1ae940a1995-01-02 19:04:15 +000072#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;
Guido van Rossum1ae940a1995-01-02 19:04:15 +0000185 sprintf(funcname, FUNCNAME_PATTERN, name);
186#ifdef WITH_MAC_DL
187 {
188 object *v = dynamic_load(pathname);
189 if (v == NULL)
190 return NULL;
191 }
192#else /* !WITH_MAC_DL */
193#ifdef USE_SHLIB
194 {
195#ifdef RTLD_NOW
196 /* RTLD_NOW: resolve externals now
197 (i.e. core dump now if some are missing) */
198 void *handle = dlopen(pathname, RTLD_NOW);
199#else
200 void *handle;
201 if (verbose)
202 printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
203 handle = dlopen(pathname, RTLD_LAZY);
204#endif /* RTLD_NOW */
205 if (handle == NULL) {
206 err_setstr(ImportError, dlerror());
207 return NULL;
208 }
209 p = (dl_funcptr) dlsym(handle, funcname);
210 }
211#endif /* USE_SHLIB */
212#ifdef _AIX
213 p = (dl_funcptr) load(pathname, 1, 0);
214 if (p == NULL) {
215 aix_loaderror(pathname);
216 return NULL;
217 }
218#endif /* _AIX */
219#ifdef NT
220 {
221 HINSTANCE hDLL;
222 hDLL = LoadLibrary(pathname);
223 if (hDLL==NULL){
224 char errBuf[64];
225 sprintf(errBuf, "DLL load failed with error code %d",
226 GetLastError());
227 err_setstr(ImportError, errBuf);
228 return NULL;
229 }
230 p = GetProcAddress(hDLL, funcname);
231 }
232#endif /* NT */
233#ifdef USE_DL
234 p = dl_loadmod(getprogramname(), pathname, funcname);
235#endif /* USE_DL */
236#ifdef USE_RLD
237 {
238 NXStream *errorStream;
239 struct mach_header *new_header;
240 const char *filenames[2];
241 long ret;
242 unsigned long ptr;
243
244 errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
245 filenames[0] = pathname;
246 filenames[1] = NULL;
247 ret = rld_load(errorStream, &new_header,
248 filenames, NULL);
249
250 /* extract the error messages for the exception */
251 if(!ret) {
252 char *streamBuf;
253 int len, maxLen;
254
255 NXPutc(errorStream, (char)0);
256
257 NXGetMemoryBuffer(errorStream,
258 &streamBuf, &len, &maxLen);
259 err_setstr(ImportError, streamBuf);
260 }
261
262 if(ret && rld_lookup(errorStream, funcname, &ptr))
263 p = (dl_funcptr) ptr;
264
265 NXCloseMemory(errorStream, NX_FREEBUFFER);
266
267 if(!ret)
268 return NULL;
269 }
270#endif /* USE_RLD */
271#ifdef hpux
272 {
273 shl_t lib;
274 int flags;
275
276 flags = BIND_DEFERRED;
277 if (verbose)
278 {
279 flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE;
280 printf("shl_load %s\n",pathname);
281 }
282 lib = shl_load(pathname, flags, 0);
283 if (lib == NULL)
284 {
285 char buf[256];
286 if (verbose)
287 perror(pathname);
288 sprintf(buf, "Failed to load %.200s", pathname);
289 err_setstr(ImportError, buf);
290 return NULL;
291 }
292 if (verbose)
293 printf("shl_findsym %s\n", funcname);
294 shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p);
295 if (p == NULL && verbose)
296 perror(funcname);
297 }
298#endif /* hpux */
299 if (p == NULL) {
300 err_setstr(ImportError,
301 "dynamic module does not define init function");
302 return NULL;
303 }
304 (*p)();
305
306#endif /* !WITH_MAC_DL */
307 m = dictlookup(import_modules, name);
308 if (m == NULL) {
309 if (err_occurred() == NULL)
310 err_setstr(SystemError,
311 "dynamic module not initialized properly");
312 return NULL;
313 }
314 if (verbose)
315 fprintf(stderr,
316 "import %s # dynamically loaded from %s\n",
317 name, pathname);
318 INCREF(m);
319 return m;
320#endif /* DYNAMIC_LINK */
321}
322
323
324#ifdef _AIX
325
326#include <ctype.h> /* for isdigit() */
327#include <errno.h> /* for global errno */
328#include <string.h> /* for strerror() */
329
330void aix_loaderror(char *pathname)
331{
332
333 char *message[8], errbuf[1024];
334 int i,j;
335
336 struct errtab {
337 int errno;
338 char *errstr;
339 } load_errtab[] = {
340 {L_ERROR_TOOMANY, "to many errors, rest skipped."},
341 {L_ERROR_NOLIB, "can't load library:"},
342 {L_ERROR_UNDEF, "can't find symbol in library:"},
343 {L_ERROR_RLDBAD,
344 "RLD index out of range or bad relocation type:"},
345 {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
346 {L_ERROR_MEMBER,
347 "file not an archive or does not contain requested member:"},
348 {L_ERROR_TYPE, "symbol table mismatch:"},
349 {L_ERROR_ALIGN, "text allignment in file is wrong."},
350 {L_ERROR_SYSTEM, "System error:"},
351 {L_ERROR_ERRNO, NULL}
352 };
353
354#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
355#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
356
357 sprintf(errbuf, " from module %.200s ", pathname);
358
359 if (!loadquery(1, &message[0], sizeof(message)))
360 ERRBUF_APPEND(strerror(errno));
361 for(i = 0; message[i] && *message[i]; i++) {
362 int nerr = atoi(message[i]);
363 for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
364 if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
365 ERRBUF_APPEND(load_errtab[i].errstr);
366 }
367 while (isdigit(*message[i])) message[i]++ ;
368 ERRBUF_APPEND(message[i]);
369 ERRBUF_APPEND("\n");
370 }
371 errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
372 err_setstr(ImportError, errbuf);
373 return;
374}
375
376#endif /* _AIX */