import less(1)
[unleashed/tickless.git] / usr / src / lib / libdll / common / dlfcn.c
blob9707eb6b80bf5bcb6ca1cebaed133949aff1731d
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1997-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
22 * provide dlopen/dlsym/dlerror interface
24 * David Korn
25 * Glenn Fowler
26 * AT&T Research
29 static const char id[] = "\n@(#)$Id: dll library (AT&T Research) 2009-04-15 $\0\n";
31 #include <ast.h>
32 #include <dlldefs.h>
33 #include <error.h>
35 #define T(x) ERROR_dictionary(x)
37 #if _BLD_dll && defined(__EXPORT__)
38 #define extern __EXPORT__
39 #endif
41 #if _hdr_dlfcn && _lib_dlopen
44 * standard
47 # include <dlfcn.h>
49 #else
50 #if _hdr_dl
53 * HP-UX
56 # include <dl.h>
57 # ifndef BIND_FIRST
58 # define BIND_FIRST 0x4
59 # endif
60 # ifndef BIND_NOSTART
61 # define BIND_NOSTART 0x10
62 # endif
64 static shl_t all;
65 static int err;
67 extern void* dlopen(const char* path, int mode)
69 void* dll;
71 if (!path)
72 return (void*)&all;
73 if (mode)
74 mode = (BIND_IMMEDIATE|BIND_FIRST|BIND_NOSTART);
75 if (!(dll = (void*)shl_load(path, mode, 0L)))
76 err = errno;
77 return dll;
80 extern int dlclose(void* dll)
82 return 0;
85 extern void* dlsym(void* dll, const char* name)
87 shl_t handle;
88 long addr;
90 handle = dll == (void*)&all ? (shl_t)0 : (shl_t)dll;
91 if (shl_findsym(&handle, name, TYPE_UNDEFINED, &addr))
93 err = errno;
94 return 0;
96 return (void*)addr;
99 extern char* dlerror(void)
101 char* msg;
103 if (!err)
104 return 0;
105 msg = fmterror(err);
106 err = 0;
107 return msg;
110 #else
111 #if _sys_ldr && _lib_loadbind
114 * rs6000
117 # include <sys/ldr.h>
118 # include <xcoff.h>
120 /* xcoff module header */
121 struct hdr
123 struct filehdr f;
124 struct aouthdr a;
125 struct scnhdr s[1];
128 static struct ld_info* ld_info;
129 static unsigned int ld_info_size = 1024;
130 static void* last_module;
131 static int err;
133 extern void* dlopen(const char* path, int mode)
135 void* dll;
137 if (!(dll = (void*)load((char*)path, mode, getenv("LIBPATH"))))
138 err = errno;
139 return dll;
142 extern int dlclose(void* dll)
144 return 0;
147 static int getquery(void)
149 if (!ld_info)
150 ld_info = malloc(ld_info_size);
151 for (;;)
153 if (!ld_info)
154 return 1;
155 if (!loadquery(L_GETINFO, ld_info, ld_info_size))
156 return 0;
157 if (errno != ENOMEM)
158 return 1;
159 ld_info = realloc(ld_info, ld_info_size *= 2);
163 /* find the loaded module whose data area contains the
164 * address passed in. Remember that procedure pointers
165 * are implemented as pointers to descriptors in the
166 * data area of the module defining the procedure
168 static struct ld_info* getinfo(void* module)
170 struct ld_info* info = ld_info;
171 register int n = 1;
173 if (!ld_info || module != last_module)
175 last_module = module;
176 if (getquery())
177 return 0;
178 info = ld_info;
180 while (n)
182 if ((char*)(info->ldinfo_dataorg) <= (char*)module &&
183 (char*)module <= ((char*)(info->ldinfo_dataorg)
184 + (unsigned)(info->ldinfo_datasize)))
185 return info;
186 if (n=info->ldinfo_next)
187 info = (void*)((char*)info + n);
189 return 0;
192 static char* getloc(struct hdr* hdr, char* data, char* name)
194 struct ldhdr* ldhdr;
195 struct ldsym* ldsym;
196 ulong datareloc;
197 ulong textreloc;
198 int i;
200 /* data is relocated by the difference between
201 * its virtual origin and where it was
202 * actually placed
204 /*N.B. o_sndata etc. are one based */
205 datareloc = (ulong)data - hdr->s[hdr->a.o_sndata-1].s_vaddr;
206 /*hdr is address of header, not text, so add text s_scnptr */
207 textreloc = (ulong)hdr + hdr->s[hdr->a.o_sntext-1].s_scnptr
208 - hdr->s[hdr->a.o_sntext-1].s_vaddr;
209 ldhdr = (void*)((char*)hdr+ hdr->s[hdr->a.o_snloader-1].s_scnptr);
210 ldsym = (void*) (ldhdr+1);
211 /* search the exports symbols */
212 for(i=0; i < ldhdr->l_nsyms;ldsym++,i++)
214 char *symname,symbuf[9];
215 char *loc;
216 /* the symbol name representation is a nuisance since
217 * 8 character names appear in l_name but may
218 * not be null terminated. This code works around
219 * that by brute force
221 if (ldsym->l_zeroes)
223 symname = symbuf;
224 memcpy(symbuf,ldsym->l_name,8);
225 symbuf[8] = 0;
227 else
228 symname = (void*)(ldsym->l_offset + (ulong)ldhdr + ldhdr->l_stoff);
229 if (strcmp(symname,name))
230 continue;
231 loc = (char*)ldsym->l_value;
232 if ((ldsym->l_scnum==hdr->a.o_sndata) ||
233 (ldsym->l_scnum==hdr->a.o_snbss))
234 loc += datareloc;
235 else if (ldsym->l_scnum==hdr->a.o_sntext)
236 loc += textreloc;
237 return loc;
239 return 0;
242 extern void* dlsym(void* handle, const char* name)
244 void* addr;
245 struct ld_info* info;
247 if (!(info = getinfo(handle)) || !(addr = getloc(info->ldinfo_textorg,info->ldinfo_dataorg,(char*)name)))
249 err = errno;
250 return 0;
252 return addr;
255 extern char* dlerror(void)
257 char* msg;
259 if (!err)
260 return 0;
261 msg = fmterror(err);
262 err = 0;
263 return msg;
266 #else
267 #if _hdr_dll && _lib_dllload
270 * MVS
273 # include <dll.h>
275 static int err;
277 extern void* dlopen(const char* path, int mode)
279 void* dll;
281 NoP(mode);
282 if (!(dll = (void*)dllload(path)))
283 err = errno;
284 return dll;
287 extern int dlclose(void* dll)
289 return 0;
292 extern void* dlsym(void* handle, const char* name)
294 void* addr;
296 if (!(addr = (void*)dllqueryfn(handle, (char*)name)))
297 err = errno;
298 return addr;
301 extern char* dlerror(void)
303 char* msg;
305 if (!err)
306 return 0;
307 msg = fmterror(err);
308 err = 0;
309 return msg;
312 #else
313 #if _hdr_mach_o_dyld
316 * mac[h]
319 # include <mach-o/dyld.h>
321 typedef const struct mach_header* NSImage;
323 typedef struct Dll_s
325 unsigned long magic;
326 NSImage image;
327 NSModule module;
328 char path[1];
329 } Dll_t;
331 #define DL_MAGIC 0x04190c04
332 #define DL_NEXT ((Dll_t*)RTLD_NEXT)
334 static const char* dlmessage = "no error";
336 static const char e_cover[] = T("cannot access covered library");
337 static const char e_handle[] = T("invalid handle");
338 static const char e_space[] = T("out of space");
339 static const char e_static[] = T("image statically linked");
340 static const char e_undefined[] = T("undefined symbol");
342 static Dll_t global = { DL_MAGIC };
344 static void undefined(const char* name)
348 static NSModule multiple(NSSymbol sym, NSModule om, NSModule nm)
350 return om;
353 static void linkedit(NSLinkEditErrors c, int n, const char* f, const char* m)
355 dlmessage = m;
358 static NSLinkEditErrorHandlers handlers =
360 undefined, multiple, linkedit
363 extern void* dlopen(const char* path, int mode)
365 Dll_t* dll;
366 int i;
367 NSObjectFileImage image;
369 static int init = 0;
371 if (!_dyld_present())
373 dlmessage = e_static;
374 return 0;
376 if (!init)
378 init = 1;
379 NSInstallLinkEditErrorHandlers(&handlers);
381 if (!path)
382 dll = &global;
383 else if (!(dll = newof(0, Dll_t, 1, strlen(path))))
385 dlmessage = e_space;
386 return 0;
388 else
390 switch (NSCreateObjectFileImageFromFile(path, &image))
392 case NSObjectFileImageSuccess:
393 dll->module = NSLinkModule(image, path, (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW);
394 NSDestroyObjectFileImage(image);
395 if (!dll->module)
397 free(dll);
398 return 0;
400 break;
401 case NSObjectFileImageInappropriateFile:
402 dll->image = NSAddImage(path, 0);
403 if (!dll->image)
405 free(dll);
406 return 0;
408 break;
409 default:
410 free(dll);
411 return 0;
413 strcpy(dll->path, path);
414 dll->magic = DL_MAGIC;
416 return (void*)dll;
419 extern int dlclose(void* handle)
421 Dll_t* dll = (Dll_t*)handle;
423 if (!dll || dll == DL_NEXT || dll->magic != DL_MAGIC)
425 dlmessage = e_handle;
426 return -1;
428 if (dll->module)
429 NSUnLinkModule(dll->module, 0);
430 free(dll);
431 return 0;
434 static NSSymbol
435 lookup(Dll_t* dll, const char* name)
437 unsigned long pun;
438 void* address;
440 if (dll == DL_NEXT)
442 if (!_dyld_func_lookup(name, &pun))
443 return 0;
444 address = (NSSymbol)pun;
446 else if (dll->module)
447 address = NSLookupSymbolInModule(dll->module, name);
448 else if (dll->image)
450 if (!NSIsSymbolNameDefinedInImage(dll->image, name))
451 return 0;
452 address = NSLookupSymbolInImage(dll->image, name, 0);
454 else
456 if (!NSIsSymbolNameDefined(name))
457 return 0;
458 address = NSLookupAndBindSymbol(name);
460 if (address)
461 address = NSAddressOfSymbol(address);
462 return address;
465 extern void* dlsym(void* handle, const char* name)
467 Dll_t* dll = (Dll_t*)handle;
468 NSSymbol address;
469 char buf[1024];
471 if (!dll || dll != DL_NEXT && (dll->magic != DL_MAGIC || !dll->image && !dll->module))
473 dlmessage = e_handle;
474 return 0;
476 if (!(address = lookup(dll, name)) && name[0] != '_' && strlen(name) < (sizeof(buf) - 1))
478 buf[0] = '_';
479 strcpy(buf + 1, name);
480 address = lookup(dll, buf);
482 if (!address)
484 dlmessage = dll == DL_NEXT ? e_cover : e_undefined;
485 return 0;
487 return (void*)address;
490 extern char* dlerror(void)
492 char* msg;
494 msg = (char*)dlmessage;
495 dlmessage = 0;
496 return msg;
499 #else
501 * punt
504 static int err;
506 extern void* dlopen(const char* path, int mode)
508 err = 1;
509 return 0;
512 extern int dlclose(void* dll)
514 err = 1;
515 return 0;
518 extern void* dlsym(void* handle, const char* name)
520 err = 1;
521 return 0;
524 extern char* dlerror(void)
526 if (!err)
527 return 0;
528 err = 0;
529 return "dynamic linking not supported";
532 #endif
533 #endif
534 #endif
535 #endif
536 #endif