[gforth] / gforth / libltdl / loaders / preopen.c  

gforth: gforth/libltdl/loaders/preopen.c


1 : anton 1.1 /* loader-preopen.c -- emulate dynamic linking using preloaded_symbols
2 :    
3 :     Copyright (C) 1998, 1999, 2000, 2004, 2006,
4 :     2007, 2008 Free Software Foundation, Inc.
5 :     Written by Thomas Tanner, 1998
6 :    
7 :     NOTE: The canonical source of this file is maintained with the
8 :     GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9 :    
10 :     GNU Libltdl is free software; you can redistribute it and/or
11 :     modify it under the terms of the GNU Lesser General Public
12 :     License as published by the Free Software Foundation; either
13 :     version 2 of the License, or (at your option) any later version.
14 :    
15 :     As a special exception to the GNU Lesser General Public License,
16 :     if you distribute this file as part of a program or library that
17 :     is built using GNU Libtool, you may include this file under the
18 :     same distribution terms that you use for the rest of that program.
19 :    
20 :     GNU Libltdl is distributed in the hope that it will be useful,
21 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     GNU Lesser General Public License for more details.
24 :    
25 :     You should have received a copy of the GNU Lesser General Public
26 :     License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27 :     copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28 :     or obtained by writing to the Free Software Foundation, Inc.,
29 :     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 :     */
31 :    
32 :     #include "lt__private.h"
33 :     #include "lt_dlloader.h"
34 :    
35 :     /* Use the preprocessor to rename non-static symbols to avoid namespace
36 :     collisions when the loader code is statically linked into libltdl.
37 :     Use the "<module_name>_LTX_" prefix so that the symbol addresses can
38 :     be fetched from the preloaded symbol list by lt_dlsym(): */
39 :     #define get_vtable preopen_LTX_get_vtable
40 :    
41 :     LT_BEGIN_C_DECLS
42 :     LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
43 :     LT_END_C_DECLS
44 :    
45 :    
46 :     /* Boilerplate code to set up the vtable for hooking this loader into
47 :     libltdl's loader list: */
48 :     static int vl_init (lt_user_data loader_data);
49 :     static int vl_exit (lt_user_data loader_data);
50 :     static lt_module vm_open (lt_user_data loader_data, const char *filename,
51 :     lt_dladvise advise);
52 :     static int vm_close (lt_user_data loader_data, lt_module module);
53 :     static void * vm_sym (lt_user_data loader_data, lt_module module,
54 :     const char *symbolname);
55 :    
56 :     static lt_dlvtable *vtable = 0;
57 :    
58 :     /* Return the vtable for this loader, only the name and sym_prefix
59 :     attributes (plus the virtual function implementations, obviously)
60 :     change between loaders. */
61 :     lt_dlvtable *
62 :     get_vtable (lt_user_data loader_data)
63 :     {
64 :     if (!vtable)
65 :     {
66 :     vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
67 :     }
68 :    
69 :     if (vtable && !vtable->name)
70 :     {
71 :     vtable->name = "lt_preopen";
72 :     vtable->sym_prefix = 0;
73 :     vtable->module_open = vm_open;
74 :     vtable->module_close = vm_close;
75 :     vtable->find_sym = vm_sym;
76 :     vtable->dlloader_init = vl_init;
77 :     vtable->dlloader_exit = vl_exit;
78 :     vtable->dlloader_data = loader_data;
79 :     vtable->priority = LT_DLLOADER_PREPEND;
80 :     }
81 :    
82 :     if (vtable && (vtable->dlloader_data != loader_data))
83 :     {
84 :     LT__SETERROR (INIT_LOADER);
85 :     return 0;
86 :     }
87 :    
88 :     return vtable;
89 :     }
90 :    
91 :    
92 :    
93 :     /* --- IMPLEMENTATION --- */
94 :    
95 :    
96 :     /* Wrapper type to chain together symbol lists of various origins. */
97 :     typedef struct symlist_chain
98 :     {
99 :     struct symlist_chain *next;
100 :     const lt_dlsymlist *symlist;
101 :     } symlist_chain;
102 :    
103 :    
104 :     static int add_symlist (const lt_dlsymlist *symlist);
105 :     static int free_symlists (void);
106 :    
107 :     /* The start of the symbol lists chain. */
108 :     static symlist_chain *preloaded_symlists = 0;
109 :    
110 :     /* A symbol list preloaded before lt_init() was called. */
111 :     static const lt_dlsymlist *default_preloaded_symbols = 0;
112 :    
113 :    
114 :     /* A function called through the vtable to initialise this loader. */
115 :     static int
116 :     vl_init (lt_user_data LT__UNUSED loader_data)
117 :     {
118 :     int errors = 0;
119 :    
120 :     preloaded_symlists = 0;
121 :     if (default_preloaded_symbols)
122 :     {
123 :     errors = lt_dlpreload (default_preloaded_symbols);
124 :     }
125 :    
126 :     return errors;
127 :     }
128 :    
129 :    
130 :     /* A function called through the vtable when this loader is no
131 :     longer needed by the application. */
132 :     static int
133 :     vl_exit (lt_user_data LT__UNUSED loader_data)
134 :     {
135 :     vtable = NULL;
136 :     free_symlists ();
137 :     return 0;
138 :     }
139 :    
140 :    
141 :     /* A function called through the vtable to open a module with this
142 :     loader. Returns an opaque representation of the newly opened
143 :     module for processing with this loader's other vtable functions. */
144 :     static lt_module
145 :     vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
146 :     lt_dladvise LT__UNUSED advise)
147 :     {
148 :     symlist_chain *lists;
149 :     lt_module module = 0;
150 :    
151 :     if (!preloaded_symlists)
152 :     {
153 :     LT__SETERROR (NO_SYMBOLS);
154 :     goto done;
155 :     }
156 :    
157 :     /* Can't use NULL as the reflective symbol header, as NULL is
158 :     used to mark the end of the entire symbol list. Self-dlpreopened
159 :     symbols follow this magic number, chosen to be an unlikely
160 :     clash with a real module name. */
161 :     if (!filename)
162 :     {
163 :     filename = "@PROGRAM@";
164 :     }
165 :    
166 :     for (lists = preloaded_symlists; lists; lists = lists->next)
167 :     {
168 :     const lt_dlsymlist *symbol;
169 :     for (symbol= lists->symlist; symbol->name; ++symbol)
170 :     {
171 :     if (!symbol->address && streq (symbol->name, filename))
172 :     {
173 :     /* If the next symbol's name and address is 0, it means
174 :     the module just contains the originator and no symbols.
175 :     In this case we pretend that we never saw the module and
176 :     hope that some other loader will be able to load the module
177 :     and have access to its symbols */
178 :     const lt_dlsymlist *next_symbol = symbol +1;
179 :     if (next_symbol->address && next_symbol->name)
180 :     {
181 :     module = (lt_module) lists->symlist;
182 :     goto done;
183 :     }
184 :     }
185 :     }
186 :     }
187 :    
188 :     LT__SETERROR (FILE_NOT_FOUND);
189 :    
190 :     done:
191 :     return module;
192 :     }
193 :    
194 :    
195 :     /* A function called through the vtable when a particular module
196 :     should be unloaded. */
197 :     static int
198 :     vm_close (lt_user_data LT__UNUSED loader_data, lt_module LT__UNUSED module)
199 :     {
200 :     /* Just to silence gcc -Wall */
201 :     module = 0;
202 :     return 0;
203 :     }
204 :    
205 :    
206 :     /* A function called through the vtable to get the address of
207 :     a symbol loaded from a particular module. */
208 :     static void *
209 :     vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
210 :     {
211 :     lt_dlsymlist *symbol = (lt_dlsymlist*) module;
212 :    
213 :     symbol +=2; /* Skip header (originator then libname). */
214 :    
215 :     while (symbol->name)
216 :     {
217 :     if (streq (symbol->name, name))
218 :     {
219 :     return symbol->address;
220 :     }
221 :    
222 :     ++symbol;
223 :     }
224 :    
225 :     LT__SETERROR (SYMBOL_NOT_FOUND);
226 :    
227 :     return 0;
228 :     }
229 :    
230 :    
231 :    
232 :     /* --- HELPER FUNCTIONS --- */
233 :    
234 :    
235 :     /* The symbol lists themselves are not allocated from the heap, but
236 :     we can unhook them and free up the chain of links between them. */
237 :     static int
238 :     free_symlists (void)
239 :     {
240 :     symlist_chain *lists;
241 :    
242 :     lists = preloaded_symlists;
243 :     while (lists)
244 :     {
245 :     symlist_chain *next = lists->next;
246 :     FREE (lists);
247 :     lists = next;
248 :     }
249 :     preloaded_symlists = 0;
250 :    
251 :     return 0;
252 :     }
253 :    
254 :     /* Add a new symbol list to the global chain. */
255 :     static int
256 :     add_symlist (const lt_dlsymlist *symlist)
257 :     {
258 :     symlist_chain *lists;
259 :     int errors = 0;
260 :    
261 :     /* Search for duplicate entries: */
262 :     for (lists = preloaded_symlists;
263 :     lists && lists->symlist != symlist; lists = lists->next)
264 :     /*NOWORK*/;
265 :    
266 :     /* Don't add the same list twice: */
267 :     if (!lists)
268 :     {
269 :     symlist_chain *tmp = (symlist_chain *) lt__zalloc (sizeof *tmp);
270 :    
271 :     if (tmp)
272 :     {
273 :     tmp->symlist = symlist;
274 :     tmp->next = preloaded_symlists;
275 :     preloaded_symlists = tmp;
276 :     }
277 :     else
278 :     {
279 :     ++errors;
280 :     }
281 :     }
282 :    
283 :     return errors;
284 :     }
285 :    
286 :    
287 :    
288 :     /* --- PRELOADING API CALL IMPLEMENTATIONS --- */
289 :    
290 :    
291 :     /* Save a default symbol list for later. */
292 :     int
293 :     lt_dlpreload_default (const lt_dlsymlist *preloaded)
294 :     {
295 :     default_preloaded_symbols = preloaded;
296 :     return 0;
297 :     }
298 :    
299 :    
300 :     /* Add a symbol list to the global chain, or with a NULL argument,
301 :     revert to just the default list. */
302 :     int
303 :     lt_dlpreload (const lt_dlsymlist *preloaded)
304 :     {
305 :     int errors = 0;
306 :    
307 :     if (preloaded)
308 :     {
309 :     errors = add_symlist (preloaded);
310 :     }
311 :     else
312 :     {
313 :     free_symlists();
314 :    
315 :     if (default_preloaded_symbols)
316 :     {
317 :     errors = lt_dlpreload (default_preloaded_symbols);
318 :     }
319 :     }
320 :    
321 :     return errors;
322 :     }
323 :    
324 :    
325 :     /* Open all the preloaded modules from the named originator, executing
326 :     a callback for each one. If ORIGINATOR is NULL, then call FUNC for
327 :     each preloaded module from the program itself. */
328 :     int
329 :     lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
330 :     {
331 :     symlist_chain *list;
332 :     int errors = 0;
333 :     int found = 0;
334 :    
335 :     /* For each symlist in the chain... */
336 :     for (list = preloaded_symlists; list; list = list->next)
337 :     {
338 :     /* ...that was preloaded by the requesting ORIGINATOR... */
339 :     if ((originator && streq (list->symlist->name, originator))
340 :     || (!originator && streq (list->symlist->name, "@PROGRAM@")))
341 :     {
342 :     const lt_dlsymlist *symbol;
343 :     unsigned int idx = 0;
344 :    
345 :     ++found;
346 :    
347 :     /* ...load the symbols per source compilation unit:
348 :     (we preincrement the index to skip over the originator entry) */
349 :     while ((symbol = &list->symlist[++idx])->name != 0)
350 :     {
351 :     if ((symbol->address == 0)
352 :     && (strneq (symbol->name, "@PROGRAM@")))
353 :     {
354 :     lt_dlhandle handle = lt_dlopen (symbol->name);
355 :     if (handle == 0)
356 :     {
357 :     ++errors;
358 :     }
359 :     else
360 :     {
361 :     errors += (*func) (handle);
362 :     }
363 :     }
364 :     }
365 :     }
366 :     }
367 :    
368 :     if (!found)
369 :     {
370 :     LT__SETERROR(CANNOT_OPEN);
371 :     ++errors;
372 :     }
373 :    
374 :     return errors;
375 :     }

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help