1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1997-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * provide dlopen/dlsym/dlerror interface
23da2e3ebdSchin  *
24da2e3ebdSchin  * David Korn
25da2e3ebdSchin  * Glenn Fowler
26da2e3ebdSchin  * AT&T Research
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin #include <ast.h>
30da2e3ebdSchin #include <dlldefs.h>
31da2e3ebdSchin #include <error.h>
32da2e3ebdSchin 
33da2e3ebdSchin #define T(x)	ERROR_dictionary(x)
34da2e3ebdSchin 
35da2e3ebdSchin #if _BLD_dll && defined(__EXPORT__)
36da2e3ebdSchin #define extern	__EXPORT__
37da2e3ebdSchin #endif
38da2e3ebdSchin 
39da2e3ebdSchin #if _hdr_dlfcn && _lib_dlopen
40da2e3ebdSchin 
41da2e3ebdSchin 	/*
42da2e3ebdSchin 	 * standard
43da2e3ebdSchin 	 */
44da2e3ebdSchin 
45da2e3ebdSchin #	include <dlfcn.h>
46da2e3ebdSchin 
47da2e3ebdSchin #else
48da2e3ebdSchin #if _hdr_dl
49da2e3ebdSchin 
50da2e3ebdSchin 	/*
51da2e3ebdSchin 	 * HP-UX
52da2e3ebdSchin  	 */
53da2e3ebdSchin 
54da2e3ebdSchin #	include <dl.h>
55da2e3ebdSchin #	ifndef BIND_FIRST
56da2e3ebdSchin #	define BIND_FIRST	0x4
57da2e3ebdSchin #	endif
58da2e3ebdSchin #	ifndef BIND_NOSTART
59da2e3ebdSchin #	define BIND_NOSTART	0x10
60da2e3ebdSchin #	endif
61da2e3ebdSchin 
62da2e3ebdSchin 	static shl_t	all;
63da2e3ebdSchin 	static int	err;
64da2e3ebdSchin 
dlopen(const char * path,int mode)65da2e3ebdSchin 	extern void* dlopen(const char* path, int mode)
66da2e3ebdSchin 	{
67da2e3ebdSchin 		void*	dll;
68da2e3ebdSchin 
69da2e3ebdSchin 		if (!path)
70da2e3ebdSchin 			return (void*)&all;
71da2e3ebdSchin 		if (mode)
72da2e3ebdSchin 			mode = (BIND_IMMEDIATE|BIND_FIRST|BIND_NOSTART);
73da2e3ebdSchin 		if (!(dll = (void*)shl_load(path, mode, 0L)))
74da2e3ebdSchin 			err = errno;
75da2e3ebdSchin 		return dll;
76da2e3ebdSchin 	}
77da2e3ebdSchin 
dlclose(void * dll)78da2e3ebdSchin 	extern int dlclose(void* dll)
79da2e3ebdSchin 	{
80da2e3ebdSchin 		return 0;
81da2e3ebdSchin 	}
82da2e3ebdSchin 
dlsym(void * dll,const char * name)83da2e3ebdSchin 	extern void* dlsym(void* dll, const char* name)
84da2e3ebdSchin 	{
85da2e3ebdSchin 		shl_t	handle;
86da2e3ebdSchin 		long	addr;
87da2e3ebdSchin 
88da2e3ebdSchin 		handle = dll == (void*)&all ? (shl_t)0 : (shl_t)dll;
89da2e3ebdSchin 		if (shl_findsym(&handle, name, TYPE_UNDEFINED, &addr))
90da2e3ebdSchin 		{
91da2e3ebdSchin 			err = errno;
92da2e3ebdSchin 			return 0;
93da2e3ebdSchin 		}
94da2e3ebdSchin 		return (void*)addr;
95da2e3ebdSchin 	}
96da2e3ebdSchin 
dlerror(void)97da2e3ebdSchin 	extern char* dlerror(void)
98da2e3ebdSchin 	{
99da2e3ebdSchin 		char*	msg;
100da2e3ebdSchin 
101da2e3ebdSchin 		if (!err)
102da2e3ebdSchin 			return 0;
103da2e3ebdSchin 		msg = fmterror(err);
104da2e3ebdSchin 		err = 0;
105da2e3ebdSchin 		return msg;
106da2e3ebdSchin 	}
107da2e3ebdSchin 
108da2e3ebdSchin #else
109da2e3ebdSchin #if _sys_ldr && _lib_loadbind
110da2e3ebdSchin 
111da2e3ebdSchin 	/*
112da2e3ebdSchin 	 * rs6000
113da2e3ebdSchin 	 */
114da2e3ebdSchin 
115da2e3ebdSchin #	include <sys/ldr.h>
116da2e3ebdSchin #	include <xcoff.h>
117da2e3ebdSchin 
118da2e3ebdSchin 	/* xcoff module header */
119da2e3ebdSchin 	struct hdr
120da2e3ebdSchin 	{
121da2e3ebdSchin 		struct filehdr	f;
122da2e3ebdSchin 		struct aouthdr	a;
123da2e3ebdSchin 		struct scnhdr	s[1];
124da2e3ebdSchin 	};
125da2e3ebdSchin 
126da2e3ebdSchin 	static struct ld_info*	ld_info;
127da2e3ebdSchin 	static unsigned int	ld_info_size = 1024;
128da2e3ebdSchin 	static void*		last_module;
129da2e3ebdSchin 	static int		err;
130da2e3ebdSchin 
dlopen(const char * path,int mode)131da2e3ebdSchin 	extern void* dlopen(const char* path, int mode)
132da2e3ebdSchin 	{
133da2e3ebdSchin 		void*	dll;
134da2e3ebdSchin 
135da2e3ebdSchin 		if (!(dll = (void*)load((char*)path, mode, getenv("LIBPATH"))))
136da2e3ebdSchin 			err = errno;
137da2e3ebdSchin 		return dll;
138da2e3ebdSchin 	}
139da2e3ebdSchin 
dlclose(void * dll)140da2e3ebdSchin 	extern int dlclose(void* dll)
141da2e3ebdSchin 	{
142da2e3ebdSchin 		return 0;
143da2e3ebdSchin 	}
144da2e3ebdSchin 
getquery(void)145da2e3ebdSchin 	static int getquery(void)
146da2e3ebdSchin 	{
147da2e3ebdSchin 		if (!ld_info)
148da2e3ebdSchin 			ld_info = malloc(ld_info_size);
149da2e3ebdSchin 		for (;;)
150da2e3ebdSchin 		{
151da2e3ebdSchin 			if (!ld_info)
152da2e3ebdSchin 				return 1;
153da2e3ebdSchin 			if (!loadquery(L_GETINFO, ld_info, ld_info_size))
154da2e3ebdSchin 				return 0;
155da2e3ebdSchin 			if (errno != ENOMEM)
156da2e3ebdSchin 				return 1;
157da2e3ebdSchin 			ld_info = realloc(ld_info, ld_info_size *= 2);
158da2e3ebdSchin 		}
159da2e3ebdSchin  	}
160da2e3ebdSchin 
161da2e3ebdSchin 	/* find the loaded module whose data area contains the
162da2e3ebdSchin 	 * address passed in. Remember that procedure pointers
163da2e3ebdSchin 	 * are implemented as pointers to descriptors in the
164da2e3ebdSchin 	 * data area of the module defining the procedure
165da2e3ebdSchin 	 */
getinfo(void * module)166da2e3ebdSchin 	static struct ld_info* getinfo(void* module)
167da2e3ebdSchin 	{
168da2e3ebdSchin 		struct ld_info*	info = ld_info;
169da2e3ebdSchin 		register int	n = 1;
170da2e3ebdSchin 
171da2e3ebdSchin 		if (!ld_info || module != last_module)
172da2e3ebdSchin 		{
173da2e3ebdSchin 			last_module = module;
174da2e3ebdSchin 			if (getquery())
175da2e3ebdSchin 				return 0;
176da2e3ebdSchin 			info = ld_info;
177da2e3ebdSchin 		}
178da2e3ebdSchin 		while (n)
179da2e3ebdSchin 		{
180da2e3ebdSchin 			if ((char*)(info->ldinfo_dataorg) <= (char*)module &&
181da2e3ebdSchin 				(char*)module <= ((char*)(info->ldinfo_dataorg)
182da2e3ebdSchin 				+ (unsigned)(info->ldinfo_datasize)))
183da2e3ebdSchin 				return info;
184da2e3ebdSchin 			if (n=info->ldinfo_next)
185da2e3ebdSchin 				info = (void*)((char*)info + n);
186da2e3ebdSchin 		}
187da2e3ebdSchin 		return 0;
188da2e3ebdSchin 	}
189da2e3ebdSchin 
getloc(struct hdr * hdr,char * data,char * name)190da2e3ebdSchin 	static char* getloc(struct hdr* hdr, char* data, char* name)
191da2e3ebdSchin 	{
192da2e3ebdSchin 		struct ldhdr*	ldhdr;
193da2e3ebdSchin 		struct ldsym*	ldsym;
194da2e3ebdSchin 		ulong		datareloc;
195da2e3ebdSchin 		ulong		textreloc;
196da2e3ebdSchin 		int		i;
197da2e3ebdSchin 
198da2e3ebdSchin 		/* data is relocated by the difference between
199da2e3ebdSchin 		 * its virtual origin and where it was
200da2e3ebdSchin 		 * actually placed
201da2e3ebdSchin 		 */
202da2e3ebdSchin 		/*N.B. o_sndata etc. are one based */
203da2e3ebdSchin 		datareloc = (ulong)data - hdr->s[hdr->a.o_sndata-1].s_vaddr;
204da2e3ebdSchin 		/*hdr is address of header, not text, so add text s_scnptr */
205da2e3ebdSchin 		textreloc = (ulong)hdr + hdr->s[hdr->a.o_sntext-1].s_scnptr
206da2e3ebdSchin 			- hdr->s[hdr->a.o_sntext-1].s_vaddr;
207da2e3ebdSchin 		ldhdr = (void*)((char*)hdr+ hdr->s[hdr->a.o_snloader-1].s_scnptr);
208da2e3ebdSchin 		ldsym = (void*) (ldhdr+1);
209da2e3ebdSchin 		/* search the exports symbols */
210da2e3ebdSchin 		for(i=0; i < ldhdr->l_nsyms;ldsym++,i++)
211da2e3ebdSchin 		{
212da2e3ebdSchin 			char *symname,symbuf[9];
213da2e3ebdSchin 			char *loc;
214da2e3ebdSchin 			/* the symbol name representation is a nuisance since
215da2e3ebdSchin 			 * 8 character names appear in l_name but may
216da2e3ebdSchin 			 * not be null terminated. This code works around
217da2e3ebdSchin 			 * that by brute force
218da2e3ebdSchin 			 */
219da2e3ebdSchin 			if (ldsym->l_zeroes)
220da2e3ebdSchin 			{
221da2e3ebdSchin 				symname = symbuf;
222da2e3ebdSchin 				memcpy(symbuf,ldsym->l_name,8);
223da2e3ebdSchin 				symbuf[8] = 0;
224da2e3ebdSchin 			}
225da2e3ebdSchin 			else
226da2e3ebdSchin 				symname = (void*)(ldsym->l_offset + (ulong)ldhdr + ldhdr->l_stoff);
227da2e3ebdSchin 			if (strcmp(symname,name))
228da2e3ebdSchin 				continue;
229da2e3ebdSchin 			loc = (char*)ldsym->l_value;
230da2e3ebdSchin 			if ((ldsym->l_scnum==hdr->a.o_sndata) ||
231da2e3ebdSchin 				(ldsym->l_scnum==hdr->a.o_snbss))
232da2e3ebdSchin 				loc += datareloc;
233da2e3ebdSchin 			else if (ldsym->l_scnum==hdr->a.o_sntext)
234da2e3ebdSchin 				loc += textreloc;
235da2e3ebdSchin 			return loc;
236da2e3ebdSchin 		}
237da2e3ebdSchin 		return 0;
238da2e3ebdSchin 	}
239da2e3ebdSchin 
dlsym(void * handle,const char * name)240da2e3ebdSchin 	extern void* dlsym(void* handle, const char* name)
241da2e3ebdSchin 	{
242da2e3ebdSchin 		void*		addr;
243da2e3ebdSchin 		struct ld_info*	info;
244da2e3ebdSchin 
245da2e3ebdSchin 		if (!(info = getinfo(handle)) || !(addr = getloc(info->ldinfo_textorg,info->ldinfo_dataorg,(char*)name)))
246da2e3ebdSchin 		{
247da2e3ebdSchin 			err = errno;
248da2e3ebdSchin 			return 0;
249da2e3ebdSchin 		}
250da2e3ebdSchin 		return addr;
251da2e3ebdSchin 	}
252da2e3ebdSchin 
dlerror(void)253da2e3ebdSchin 	extern char* dlerror(void)
254da2e3ebdSchin 	{
255da2e3ebdSchin 		char*	msg;
256da2e3ebdSchin 
257da2e3ebdSchin 		if (!err)
258da2e3ebdSchin 			return 0;
259da2e3ebdSchin 		msg = fmterror(err);
260da2e3ebdSchin 		err = 0;
261da2e3ebdSchin 		return msg;
262da2e3ebdSchin 	}
263da2e3ebdSchin 
264da2e3ebdSchin #else
265da2e3ebdSchin #if _hdr_dll && _lib_dllload
266da2e3ebdSchin 
267da2e3ebdSchin 	/*
268da2e3ebdSchin 	 * MVS
269da2e3ebdSchin 	 */
270da2e3ebdSchin 
271da2e3ebdSchin #	include <dll.h>
272da2e3ebdSchin 
273da2e3ebdSchin 	static int	err;
274da2e3ebdSchin 
dlopen(const char * path,int mode)275da2e3ebdSchin 	extern void* dlopen(const char* path, int mode)
276da2e3ebdSchin 	{
277da2e3ebdSchin 		void*	dll;
278da2e3ebdSchin 
279da2e3ebdSchin 		NoP(mode);
280da2e3ebdSchin 		if (!(dll = (void*)dllload(path)))
281da2e3ebdSchin 			err = errno;
282da2e3ebdSchin 		return dll;
283da2e3ebdSchin 	}
284da2e3ebdSchin 
dlclose(void * dll)285da2e3ebdSchin 	extern int dlclose(void* dll)
286da2e3ebdSchin 	{
287da2e3ebdSchin 		return 0;
288da2e3ebdSchin 	}
289da2e3ebdSchin 
dlsym(void * handle,const char * name)290da2e3ebdSchin 	extern void* dlsym(void* handle, const char* name)
291da2e3ebdSchin 	{
292da2e3ebdSchin 		void*	addr;
293da2e3ebdSchin 
294da2e3ebdSchin 		if (!(addr = (void*)dllqueryfn(handle, (char*)name)))
295da2e3ebdSchin 			err = errno;
296da2e3ebdSchin 		return addr;
297da2e3ebdSchin 	}
298da2e3ebdSchin 
dlerror(void)299da2e3ebdSchin 	extern char* dlerror(void)
300da2e3ebdSchin 	{
301da2e3ebdSchin 		char*	msg;
302da2e3ebdSchin 
303da2e3ebdSchin 		if (!err)
304da2e3ebdSchin 			return 0;
305da2e3ebdSchin 		msg = fmterror(err);
306da2e3ebdSchin 		err = 0;
307da2e3ebdSchin 		return msg;
308da2e3ebdSchin 	}
309da2e3ebdSchin 
310da2e3ebdSchin #else
311da2e3ebdSchin #if _hdr_mach_o_dyld
312da2e3ebdSchin 
313da2e3ebdSchin 	/*
314da2e3ebdSchin 	 * mac[h]
315da2e3ebdSchin 	 */
316da2e3ebdSchin 
317da2e3ebdSchin #	include <mach-o/dyld.h>
318da2e3ebdSchin 
319da2e3ebdSchin 	typedef const struct mach_header* NSImage;
320da2e3ebdSchin 
321da2e3ebdSchin 	typedef struct Dll_s
322da2e3ebdSchin 	{
323da2e3ebdSchin 		unsigned long	magic;
324da2e3ebdSchin 		NSImage		image;
325da2e3ebdSchin 		NSModule	module;
326da2e3ebdSchin 		char		path[1];
327da2e3ebdSchin 	} Dll_t;
328da2e3ebdSchin 
329da2e3ebdSchin 	#define DL_MAGIC	0x04190c04
330da2e3ebdSchin 	#define DL_NEXT		((Dll_t*)RTLD_NEXT)
331da2e3ebdSchin 
332da2e3ebdSchin 	static const char*	dlmessage = "no error";
333da2e3ebdSchin 
334da2e3ebdSchin 	static const char	e_cover[] = T("cannot access covered library");
335da2e3ebdSchin 	static const char	e_handle[] = T("invalid handle");
336da2e3ebdSchin 	static const char	e_space[] = T("out of space");
337da2e3ebdSchin 	static const char	e_static[] = T("image statically linked");
338da2e3ebdSchin 	static const char	e_undefined[] = T("undefined symbol");
339da2e3ebdSchin 
340da2e3ebdSchin 	static Dll_t global = { DL_MAGIC };
341da2e3ebdSchin 
undefined(const char * name)342da2e3ebdSchin 	static void undefined(const char* name)
343da2e3ebdSchin 	{
344da2e3ebdSchin 	}
345da2e3ebdSchin 
multiple(NSSymbol sym,NSModule om,NSModule nm)346da2e3ebdSchin 	static NSModule multiple(NSSymbol sym, NSModule om, NSModule nm)
347da2e3ebdSchin 	{
348da2e3ebdSchin 		return om;
349da2e3ebdSchin 	}
350da2e3ebdSchin 
linkedit(NSLinkEditErrors c,int n,const char * f,const char * m)351da2e3ebdSchin 	static void linkedit(NSLinkEditErrors c, int n, const char* f, const char* m)
352da2e3ebdSchin 	{
353da2e3ebdSchin 		dlmessage = m;
354da2e3ebdSchin 	}
355da2e3ebdSchin 
356da2e3ebdSchin 	static NSLinkEditErrorHandlers handlers =
357da2e3ebdSchin 	{
358da2e3ebdSchin 		undefined, multiple, linkedit
359da2e3ebdSchin 	};
360da2e3ebdSchin 
dlopen(const char * path,int mode)361da2e3ebdSchin 	extern void* dlopen(const char* path, int mode)
362da2e3ebdSchin 	{
363da2e3ebdSchin 		Dll_t*			dll;
364da2e3ebdSchin 		int			i;
365da2e3ebdSchin 		NSObjectFileImage	image;
366da2e3ebdSchin 
367da2e3ebdSchin 		static int		init = 0;
368da2e3ebdSchin 
369da2e3ebdSchin 		if (!_dyld_present())
370da2e3ebdSchin 		{
371da2e3ebdSchin 			dlmessage = e_static;
372da2e3ebdSchin 			return 0;
373da2e3ebdSchin 		}
374da2e3ebdSchin 		if (!init)
375da2e3ebdSchin 		{
376da2e3ebdSchin 			init = 1;
377da2e3ebdSchin 			NSInstallLinkEditErrorHandlers(&handlers);
378da2e3ebdSchin 		}
379da2e3ebdSchin 		if (!path)
380da2e3ebdSchin 			dll = &global;
381da2e3ebdSchin 		else if (!(dll = newof(0, Dll_t, 1, strlen(path))))
382da2e3ebdSchin 		{
383da2e3ebdSchin 			dlmessage = e_space;
384da2e3ebdSchin 			return 0;
385da2e3ebdSchin 		}
386da2e3ebdSchin 		else
387da2e3ebdSchin 		{
388da2e3ebdSchin 			switch (NSCreateObjectFileImageFromFile(path, &image))
389da2e3ebdSchin 			{
390da2e3ebdSchin 			case NSObjectFileImageSuccess:
391da2e3ebdSchin 				dll->module = NSLinkModule(image, path, (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW);
392da2e3ebdSchin 				NSDestroyObjectFileImage(image);
393da2e3ebdSchin 				if (!dll->module)
394da2e3ebdSchin 				{
395da2e3ebdSchin 					free(dll);
396da2e3ebdSchin 					return 0;
397da2e3ebdSchin 				}
398da2e3ebdSchin 				break;
399da2e3ebdSchin 			case NSObjectFileImageInappropriateFile:
400da2e3ebdSchin 				dll->image = NSAddImage(path, 0);
401da2e3ebdSchin 				if (!dll->image)
402da2e3ebdSchin 				{
403da2e3ebdSchin 					free(dll);
404da2e3ebdSchin 					return 0;
405da2e3ebdSchin 				}
406da2e3ebdSchin 				break;
407da2e3ebdSchin 			default:
408da2e3ebdSchin 				free(dll);
409da2e3ebdSchin 				return 0;
410da2e3ebdSchin 			}
411da2e3ebdSchin 			strcpy(dll->path, path);
412da2e3ebdSchin 			dll->magic = DL_MAGIC;
413da2e3ebdSchin 		}
414da2e3ebdSchin 		return (void*)dll;
415da2e3ebdSchin 	}
416da2e3ebdSchin 
dlclose(void * handle)417da2e3ebdSchin 	extern int dlclose(void* handle)
418da2e3ebdSchin 	{
419da2e3ebdSchin 		Dll_t*	dll = (Dll_t*)handle;
420da2e3ebdSchin 
421da2e3ebdSchin 		if (!dll || dll == DL_NEXT || dll->magic != DL_MAGIC)
422da2e3ebdSchin 		{
423da2e3ebdSchin 			dlmessage = e_handle;
424da2e3ebdSchin 			return -1;
425da2e3ebdSchin 		}
426da2e3ebdSchin 		if (dll->module)
427da2e3ebdSchin 			NSUnLinkModule(dll->module, 0);
428da2e3ebdSchin 		free(dll);
429da2e3ebdSchin 		return 0;
430da2e3ebdSchin 	}
431da2e3ebdSchin 
432da2e3ebdSchin 	static NSSymbol
lookup(Dll_t * dll,const char * name)433da2e3ebdSchin 	lookup(Dll_t* dll, const char* name)
434da2e3ebdSchin 	{
435da2e3ebdSchin 		unsigned long	pun;
436da2e3ebdSchin 		void*		address;
437da2e3ebdSchin 
438da2e3ebdSchin 		if (dll == DL_NEXT)
439da2e3ebdSchin 		{
440da2e3ebdSchin 			if (!_dyld_func_lookup(name, &pun))
441da2e3ebdSchin 				return 0;
442da2e3ebdSchin 			address = (NSSymbol)pun;
443da2e3ebdSchin 		}
444da2e3ebdSchin 		else if (dll->module)
445da2e3ebdSchin 			address = NSLookupSymbolInModule(dll->module, name);
446da2e3ebdSchin 		else if (dll->image)
447da2e3ebdSchin 		{
448da2e3ebdSchin 			if (!NSIsSymbolNameDefinedInImage(dll->image, name))
449da2e3ebdSchin 				return 0;
450da2e3ebdSchin 			address = NSLookupSymbolInImage(dll->image, name, 0);
451da2e3ebdSchin 		}
452da2e3ebdSchin 		else
453da2e3ebdSchin 		{
454da2e3ebdSchin 			if (!NSIsSymbolNameDefined(name))
455da2e3ebdSchin 				return 0;
456da2e3ebdSchin 			address = NSLookupAndBindSymbol(name);
457da2e3ebdSchin 		}
458da2e3ebdSchin 		if (address)
459da2e3ebdSchin 			address = NSAddressOfSymbol(address);
460da2e3ebdSchin 		return address;
461da2e3ebdSchin 	}
462da2e3ebdSchin 
dlsym(void * handle,const char * name)463da2e3ebdSchin 	extern void* dlsym(void* handle, const char* name)
464da2e3ebdSchin 	{
465da2e3ebdSchin 		Dll_t*		dll = (Dll_t*)handle;
466da2e3ebdSchin 		NSSymbol	address;
467da2e3ebdSchin 		char		buf[1024];
468da2e3ebdSchin 
469da2e3ebdSchin 		if (!dll || dll != DL_NEXT && (dll->magic != DL_MAGIC || !dll->image && !dll->module))
470da2e3ebdSchin 		{
471da2e3ebdSchin 			dlmessage = e_handle;
472da2e3ebdSchin 			return 0;
473da2e3ebdSchin 		}
474da2e3ebdSchin 		if (!(address = lookup(dll, name)) && name[0] != '_' && strlen(name) < (sizeof(buf) - 1))
475da2e3ebdSchin 		{
476da2e3ebdSchin 			buf[0] = '_';
477da2e3ebdSchin 			strcpy(buf + 1, name);
478da2e3ebdSchin 			address = lookup(dll, buf);
479da2e3ebdSchin 		}
480da2e3ebdSchin 		if (!address)
481da2e3ebdSchin 		{
482da2e3ebdSchin 			dlmessage = dll == DL_NEXT ? e_cover : e_undefined;
483da2e3ebdSchin 			return 0;
484da2e3ebdSchin 		}
485da2e3ebdSchin 		return (void*)address;
486da2e3ebdSchin 	}
487da2e3ebdSchin 
dlerror(void)488da2e3ebdSchin 	extern char* dlerror(void)
489da2e3ebdSchin 	{
490da2e3ebdSchin 		char*	msg;
491da2e3ebdSchin 
492da2e3ebdSchin 		msg = (char*)dlmessage;
493da2e3ebdSchin 		dlmessage = 0;
494da2e3ebdSchin 		return msg;
495da2e3ebdSchin 	}
496da2e3ebdSchin 
497da2e3ebdSchin #else
498da2e3ebdSchin 	/*
499da2e3ebdSchin 	 * punt
500da2e3ebdSchin 	 */
501da2e3ebdSchin 
502da2e3ebdSchin 	static int	err;
503da2e3ebdSchin 
dlopen(const char * path,int mode)504da2e3ebdSchin 	extern void* dlopen(const char* path, int mode)
505da2e3ebdSchin 	{
506da2e3ebdSchin 		err = 1;
507da2e3ebdSchin 		return 0;
508da2e3ebdSchin 	}
509da2e3ebdSchin 
dlclose(void * dll)510da2e3ebdSchin 	extern int dlclose(void* dll)
511da2e3ebdSchin 	{
512da2e3ebdSchin 		err = 1;
513da2e3ebdSchin 		return 0;
514da2e3ebdSchin 	}
515da2e3ebdSchin 
dlsym(void * handle,const char * name)516da2e3ebdSchin 	extern void* dlsym(void* handle, const char* name)
517da2e3ebdSchin 	{
518da2e3ebdSchin 		err = 1;
519da2e3ebdSchin 		return 0;
520da2e3ebdSchin 	}
521da2e3ebdSchin 
dlerror(void)522da2e3ebdSchin 	extern char* dlerror(void)
523da2e3ebdSchin 	{
524da2e3ebdSchin 		if (!err)
525da2e3ebdSchin 			return 0;
526da2e3ebdSchin 		err = 0;
527da2e3ebdSchin 		return "dynamic linking not supported";
528da2e3ebdSchin 	}
529da2e3ebdSchin 
530da2e3ebdSchin #endif
531da2e3ebdSchin #endif
532da2e3ebdSchin #endif
533da2e3ebdSchin #endif
534da2e3ebdSchin #endif
535