1 /* loadlib.c
2 *
3 * $Id$
4 *
5 * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin
6 * Copyright 2002, 2003 Sam Hocevar <sam@hocevar.net>, Paris
7 *
8 * This software was derived from Elk 1.2, which was Copyright 1987, 1988,
9 * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written
10 * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project
11 * between TELES and Nixdorf Microprocessor Engineering, Berlin).
12 *
13 * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co-
14 * owners or individual owners of copyright in this software, grant to any
15 * person or company a worldwide, royalty free, license to
16 *
17 * i) copy this software,
18 * ii) prepare derivative works based on this software,
19 * iii) distribute copies of this software or derivative works,
20 * iv) perform this software, or
21 * v) display this software,
22 *
23 * provided that this notice is not removed and that neither Oliver Laumann
24 * nor Teles nor Nixdorf are deemed to have made any representations as to
25 * the suitability of this software for any purpose nor are held responsible
26 * for any defects of this software.
27 *
28 * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
29 */
30
31 #include "config.h"
32
33 #ifdef CAN_LOAD_LIB
34
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 #if defined (HAVE_DL_DYLD)
41 # if defined (HAVE_MACH_O_DYLD_H)
42 # include <mach-o/dyld.h>
43 # endif
44 #elif defined (HAVE_DL_WINDOWS)
45 # include <windows.h>
46 #elif defined (HAVE_DL_BEOS)
47 # if defined (HAVE_IMAGE_H)
48 # include <image.h>
49 # endif
50 #elif defined (HAVE_DL_DLOPEN)
51 # if defined (HAVE_DLFCN_H)
52 # include <dlfcn.h>
53 # endif
54 # if defined (HAVE_SYS_DL_H)
55 # include <sys/dl.h>
56 # endif
57 #elif defined (HAVE_DL_SHL_LOAD)
58 # if defined (HAVE_DL_H)
59 # include <dl.h>
60 # endif
61 #endif
62
63 #include "kernel.h"
64
65 extern void Free_Symbols (SYMTAB *);
66 extern void Call_Initializers (SYMTAB *, char *, int);
67
Dlopen_File(char * obj)68 void Dlopen_File (char *obj) {
69 SYM *sp;
70
71 #if defined (HAVE_DL_DYLD)
72 NSModule handle;
73 NSObjectFileImage image;
74 NSObjectFileImageReturnCode ret;
75
76 if (Verb_Load)
77 printf ("[dyld %s]\n", obj);
78
79 ret = NSCreateObjectFileImageFromFile (obj, &image);
80
81 if (ret != NSObjectFileImageSuccess)
82 Primitive_Error ("could not map `~%~s'",
83 Make_String (obj, strlen (obj)));
84
85 /* Open the dynamic module */
86 handle = NSLinkModule (image, obj, NSLINKMODULE_OPTION_RETURN_ON_ERROR);
87
88 if (!handle) {
89 NSLinkEditErrors errors;
90 const char *file, *err;
91 int errnum;
92 NSLinkEditError (&errors, &errnum, &file, &err);
93 Primitive_Error ("could not dyld `~%~s': ~%~s",
94 Make_String (file, strlen (file)),
95 Make_String (err, strlen (err)));
96 }
97
98 /* Destroy our image, we won't need it */
99 NSDestroyObjectFileImage (image);
100
101 /* NSUnLinkModule (handle, FALSE); */
102
103 #elif defined (HAVE_DL_WINDOWS)
104 void *handle;
105
106 if (Verb_Load)
107 printf ("[dll %s]\n", obj);
108
109 handle = LoadLibrary (obj);
110
111 if (handle == NULL) {
112 Primitive_Error ("LoadLibrary failed on ~%~s",
113 Make_String (obj, strlen (obj)));
114 }
115
116 #elif defined (HAVE_DL_BEOS)
117 int handle;
118
119 if (Verb_Load)
120 printf ("[load_add_on %s]\n", obj);
121
122 handle = load_add_on (obj);
123
124 if (handle < 0) {
125 Primitive_Error ("load_add_on failed on ~%~s",
126 Make_String (obj, strlen (obj)));
127 }
128
129 #elif defined (HAVE_DL_DLOPEN)
130 void *handle;
131
132 if (Verb_Load)
133 printf ("[dlopen %s]\n", obj);
134
135 #if defined (RTLD_GLOBAL)
136 handle = dlopen (obj, RTLD_NOW | RTLD_GLOBAL);
137 #elif defined (DL_GLOBAL)
138 handle = dlopen (obj, DL_NOW | DL_GLOBAL);
139 #else
140 handle = dlopen (obj, 0);
141 #endif
142
143 if (handle == NULL) {
144 char *err = dlerror ();
145 Primitive_Error ("dlopen failed: ~%~s",
146 Make_String (err, strlen (err)));
147 }
148
149 #elif defined (HAVE_DL_SHL_LOAD)
150 shl_t handle;
151
152 if (Verb_Load)
153 printf ("[shl_load %s]\n", obj);
154
155 handle = shl_load (obj, BIND_IMMEDIATE | BIND_NONFATAL, NULL);
156
157 if (handle == NULL) {
158 char *err = strerror (errno);
159 Primitive_Error ("shl_load failed: ~%~s",
160 Make_String (err, strlen (err)));
161 }
162
163 #else
164 # error "No dynamic plugins API"
165 #endif
166
167 if (The_Symbols)
168 Free_Symbols (The_Symbols);
169
170 The_Symbols = Open_File_And_Snarf_Symbols (obj);
171 for (sp = The_Symbols->first; sp; sp = sp->next) {
172 #if defined (HAVE_DL_DYLD)
173 NSSymbol sym = NSLookupSymbolInModule (handle, sp->name);
174 if (sym)
175 sp->value = (unsigned long int)(intptr_t)NSAddressOfSymbol (sym);
176
177 #elif defined (HAVE_DL_WINDOWS)
178 sp->value = (unsigned long int)(intptr_t)GetProcAddress (handle, sp->name);
179
180 #elif defined (HAVE_DL_BEOS)
181 void *sym;
182 if (get_image_symbol (handle, sp->name, B_SYMBOL_TYPE_TEXT, &sym)
183 == B_OK) {
184 sp->value = (unsigned long int)(intptr_t)sym;
185 }
186
187 #elif defined (HAVE_DL_DLOPEN)
188 /* dlsym() may fail for symbols not exported by object file;
189 * this can be safely ignored. */
190 sp->value = (unsigned long int)(intptr_t)dlsym (handle, sp->name);
191
192 #elif defined (HAVE_DL_SHL_LOAD)
193 void *sym;
194 shl_findsym (&handle, sp->name, TYPE_UNDEFINED, &sym);
195 sp->value = (unsigned long int)(intptr_t)sym;
196 #endif
197 }
198
199 Call_Initializers (The_Symbols, 0, PR_CONSTRUCTOR);
200 Call_Initializers (The_Symbols, 0, PR_EXTENSION);
201 }
202
Load_Lib(Object libs)203 static void Load_Lib (Object libs) {
204 char *lib = NULL;
205 Object port, name;
206 GC_Node2;
207
208 if (Nullp (libs))
209 return;
210
211 Load_Lib (Cdr (libs));
212
213 port = name = Null;
214 GC_Link2 (port, name);
215
216 /* Read the libtool object to find our library's name */
217 port = General_Open_File (Car (libs), P_INPUT, Var_Get (V_Load_Path));
218 while (!feof (PORT(port)->file)) {
219 char buffer [BUFSIZ], *dlname, *eol, *path;
220 if (fgets (buffer, BUFSIZ, PORT(port)->file) == NULL)
221 break;
222 buffer[BUFSIZ-1] = '\0';
223 /* Our line starts with dlname='... */
224 if (strncmp (buffer, "dlname", 6))
225 continue;
226 dlname = strchr (buffer, '\'');
227 if (dlname == NULL)
228 continue;
229 dlname++;
230 eol = strrchr (buffer, '\'');
231 if (eol == NULL || eol == dlname)
232 continue;
233 *eol = '\0';
234 path = Get_String (PORT(port)->name);
235 eol = strrchr (path, SEPARATOR_CHAR);
236 if (eol == NULL)
237 eol = path;
238 *eol = '\0';
239 lib = malloc (strlen (path) + 1 + strlen (dlname) + 1);
240 sprintf (lib, "%s" SEPARATOR_STRING "%s", path, dlname);
241 break;
242 }
243 (void)P_Close_Input_Port (port);
244
245 if (lib)
246 Dlopen_File (lib);
247
248 GC_Unlink;
249 }
250
Load_Library(Object libs)251 void Load_Library (Object libs) {
252 Disable_Interrupts;
253 Load_Lib (libs);
254 Enable_Interrupts;
255 }
256
257 #endif /* CAN_LOAD_LIB */
258
259