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