1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
22 * provide dlopen/dlsym/dlerror interface
29 static const char id
[] = "\n@(#)$Id: dll library (AT&T Research) 2009-04-15 $\0\n";
35 #define T(x) ERROR_dictionary(x)
37 #if _BLD_dll && defined(__EXPORT__)
38 #define extern __EXPORT__
41 #if _hdr_dlfcn && _lib_dlopen
58 # define BIND_FIRST 0x4
61 # define BIND_NOSTART 0x10
67 extern void* dlopen(const char* path
, int mode
)
74 mode
= (BIND_IMMEDIATE
|BIND_FIRST
|BIND_NOSTART
);
75 if (!(dll
= (void*)shl_load(path
, mode
, 0L)))
80 extern int dlclose(void* dll
)
85 extern void* dlsym(void* dll
, const char* name
)
90 handle
= dll
== (void*)&all
? (shl_t
)0 : (shl_t
)dll
;
91 if (shl_findsym(&handle
, name
, TYPE_UNDEFINED
, &addr
))
99 extern char* dlerror(void)
111 #if _sys_ldr && _lib_loadbind
117 # include <sys/ldr.h>
120 /* xcoff module header */
128 static struct ld_info
* ld_info
;
129 static unsigned int ld_info_size
= 1024;
130 static void* last_module
;
133 extern void* dlopen(const char* path
, int mode
)
137 if (!(dll
= (void*)load((char*)path
, mode
, getenv("LIBPATH"))))
142 extern int dlclose(void* dll
)
147 static int getquery(void)
150 ld_info
= malloc(ld_info_size
);
155 if (!loadquery(L_GETINFO
, ld_info
, ld_info_size
))
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
;
173 if (!ld_info
|| module
!= last_module
)
175 last_module
= module
;
182 if ((char*)(info
->ldinfo_dataorg
) <= (char*)module
&&
183 (char*)module
<= ((char*)(info
->ldinfo_dataorg
)
184 + (unsigned)(info
->ldinfo_datasize
)))
186 if (n
=info
->ldinfo_next
)
187 info
= (void*)((char*)info
+ n
);
192 static char* getloc(struct hdr
* hdr
, char* data
, char* name
)
200 /* data is relocated by the difference between
201 * its virtual origin and where it was
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];
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
224 memcpy(symbuf
,ldsym
->l_name
,8);
228 symname
= (void*)(ldsym
->l_offset
+ (ulong
)ldhdr
+ ldhdr
->l_stoff
);
229 if (strcmp(symname
,name
))
231 loc
= (char*)ldsym
->l_value
;
232 if ((ldsym
->l_scnum
==hdr
->a
.o_sndata
) ||
233 (ldsym
->l_scnum
==hdr
->a
.o_snbss
))
235 else if (ldsym
->l_scnum
==hdr
->a
.o_sntext
)
242 extern void* dlsym(void* handle
, const char* name
)
245 struct ld_info
* info
;
247 if (!(info
= getinfo(handle
)) || !(addr
= getloc(info
->ldinfo_textorg
,info
->ldinfo_dataorg
,(char*)name
)))
255 extern char* dlerror(void)
267 #if _hdr_dll && _lib_dllload
277 extern void* dlopen(const char* path
, int mode
)
282 if (!(dll
= (void*)dllload(path
)))
287 extern int dlclose(void* dll
)
292 extern void* dlsym(void* handle
, const char* name
)
296 if (!(addr
= (void*)dllqueryfn(handle
, (char*)name
)))
301 extern char* dlerror(void)
319 # include <mach-o/dyld.h>
321 typedef const struct mach_header
* NSImage
;
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
)
353 static void linkedit(NSLinkEditErrors c
, int n
, const char* f
, const char* m
)
358 static NSLinkEditErrorHandlers handlers
=
360 undefined
, multiple
, linkedit
363 extern void* dlopen(const char* path
, int mode
)
367 NSObjectFileImage image
;
371 if (!_dyld_present())
373 dlmessage
= e_static
;
379 NSInstallLinkEditErrorHandlers(&handlers
);
383 else if (!(dll
= newof(0, Dll_t
, 1, strlen(path
))))
390 switch (NSCreateObjectFileImageFromFile(path
, &image
))
392 case NSObjectFileImageSuccess
:
393 dll
->module
= NSLinkModule(image
, path
, (mode
& RTLD_LAZY
) ? 0 : NSLINKMODULE_OPTION_BINDNOW
);
394 NSDestroyObjectFileImage(image
);
401 case NSObjectFileImageInappropriateFile
:
402 dll
->image
= NSAddImage(path
, 0);
413 strcpy(dll
->path
, path
);
414 dll
->magic
= DL_MAGIC
;
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
;
429 NSUnLinkModule(dll
->module
, 0);
435 lookup(Dll_t
* dll
, const char* name
)
442 if (!_dyld_func_lookup(name
, &pun
))
444 address
= (NSSymbol
)pun
;
446 else if (dll
->module
)
447 address
= NSLookupSymbolInModule(dll
->module
, name
);
450 if (!NSIsSymbolNameDefinedInImage(dll
->image
, name
))
452 address
= NSLookupSymbolInImage(dll
->image
, name
, 0);
456 if (!NSIsSymbolNameDefined(name
))
458 address
= NSLookupAndBindSymbol(name
);
461 address
= NSAddressOfSymbol(address
);
465 extern void* dlsym(void* handle
, const char* name
)
467 Dll_t
* dll
= (Dll_t
*)handle
;
471 if (!dll
|| dll
!= DL_NEXT
&& (dll
->magic
!= DL_MAGIC
|| !dll
->image
&& !dll
->module
))
473 dlmessage
= e_handle
;
476 if (!(address
= lookup(dll
, name
)) && name
[0] != '_' && strlen(name
) < (sizeof(buf
) - 1))
479 strcpy(buf
+ 1, name
);
480 address
= lookup(dll
, buf
);
484 dlmessage
= dll
== DL_NEXT
? e_cover
: e_undefined
;
487 return (void*)address
;
490 extern char* dlerror(void)
494 msg
= (char*)dlmessage
;
506 extern void* dlopen(const char* path
, int mode
)
512 extern int dlclose(void* dll
)
518 extern void* dlsym(void* handle
, const char* name
)
524 extern char* dlerror(void)
529 return "dynamic linking not supported";