xref: /titanic_53/usr/src/contrib/ast/src/lib/libdll/dllnext.c (revision 906afcb89d0412cc073b95c2d701a804a8cdb62c)
1*906afcb8SAndy Fiddaman /***********************************************************************
2*906afcb8SAndy Fiddaman *                                                                      *
3*906afcb8SAndy Fiddaman *               This software is part of the ast package               *
4*906afcb8SAndy Fiddaman *          Copyright (c) 1997-2011 AT&T Intellectual Property          *
5*906afcb8SAndy Fiddaman *                      and is licensed under the                       *
6*906afcb8SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*906afcb8SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*906afcb8SAndy Fiddaman *                                                                      *
9*906afcb8SAndy Fiddaman *                A copy of the License is available at                 *
10*906afcb8SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*906afcb8SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*906afcb8SAndy Fiddaman *                                                                      *
13*906afcb8SAndy Fiddaman *              Information and Software Systems Research               *
14*906afcb8SAndy Fiddaman *                            AT&T Research                             *
15*906afcb8SAndy Fiddaman *                           Florham Park NJ                            *
16*906afcb8SAndy Fiddaman *                                                                      *
17*906afcb8SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*906afcb8SAndy Fiddaman *                                                                      *
19*906afcb8SAndy Fiddaman ***********************************************************************/
20*906afcb8SAndy Fiddaman #pragma prototyped
21*906afcb8SAndy Fiddaman /*
22*906afcb8SAndy Fiddaman  * Glenn Fowler
23*906afcb8SAndy Fiddaman  * AT&T Research
24*906afcb8SAndy Fiddaman  */
25*906afcb8SAndy Fiddaman 
26*906afcb8SAndy Fiddaman #ifndef _GNU_SOURCE
27*906afcb8SAndy Fiddaman #define _GNU_SOURCE	1
28*906afcb8SAndy Fiddaman #endif
29*906afcb8SAndy Fiddaman #ifndef __EXTENSIONS__
30*906afcb8SAndy Fiddaman #define __EXTENSIONS__	1
31*906afcb8SAndy Fiddaman #endif
32*906afcb8SAndy Fiddaman 
33*906afcb8SAndy Fiddaman #include <ast.h>
34*906afcb8SAndy Fiddaman #include <dlldefs.h>
35*906afcb8SAndy Fiddaman 
36*906afcb8SAndy Fiddaman #if _hdr_rld_interface
37*906afcb8SAndy Fiddaman #include <rld_interface.h>
38*906afcb8SAndy Fiddaman #endif
39*906afcb8SAndy Fiddaman 
40*906afcb8SAndy Fiddaman /*
41*906afcb8SAndy Fiddaman  * return a handle for the next layer down,
42*906afcb8SAndy Fiddaman  * i.e., the next layer that has symbols covered
43*906afcb8SAndy Fiddaman  * by the main prog and dll's loaded so far
44*906afcb8SAndy Fiddaman  *
45*906afcb8SAndy Fiddaman  * intentionally light on external lib calls
46*906afcb8SAndy Fiddaman  * so this routine can be used early in process
47*906afcb8SAndy Fiddaman  * startup
48*906afcb8SAndy Fiddaman  */
49*906afcb8SAndy Fiddaman 
50*906afcb8SAndy Fiddaman #ifdef	_DLL_RLD_SYM
51*906afcb8SAndy Fiddaman 
52*906afcb8SAndy Fiddaman #define DEBUG		1
53*906afcb8SAndy Fiddaman 
54*906afcb8SAndy Fiddaman #if DEBUG
55*906afcb8SAndy Fiddaman 
56*906afcb8SAndy Fiddaman typedef ssize_t (*Write_f)(int, const void*, size_t);
57*906afcb8SAndy Fiddaman 
58*906afcb8SAndy Fiddaman #endif
59*906afcb8SAndy Fiddaman 
60*906afcb8SAndy Fiddaman #undef	dllnext
61*906afcb8SAndy Fiddaman 
62*906afcb8SAndy Fiddaman void*
_dll_next(int flags,_DLL_RLD_SYM_TYPE * here)63*906afcb8SAndy Fiddaman _dll_next(int flags, _DLL_RLD_SYM_TYPE* here)
64*906afcb8SAndy Fiddaman {
65*906afcb8SAndy Fiddaman 	register char*	vp;
66*906afcb8SAndy Fiddaman 	register void*	lp;
67*906afcb8SAndy Fiddaman 	register int	found = 0;
68*906afcb8SAndy Fiddaman 	char*		s;
69*906afcb8SAndy Fiddaman 	char*		b;
70*906afcb8SAndy Fiddaman 	char*		e;
71*906afcb8SAndy Fiddaman 	char		dummy[256];
72*906afcb8SAndy Fiddaman #if DEBUG
73*906afcb8SAndy Fiddaman 	Write_f		wr = 0;
74*906afcb8SAndy Fiddaman 	Write_f		xr;
75*906afcb8SAndy Fiddaman 	char		buf[1024];
76*906afcb8SAndy Fiddaman #endif
77*906afcb8SAndy Fiddaman 
78*906afcb8SAndy Fiddaman #if DEBUG
79*906afcb8SAndy Fiddaman 	if (getenv("DLL_DEBUG") && (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME)))
80*906afcb8SAndy Fiddaman 	{
81*906afcb8SAndy Fiddaman 		do
82*906afcb8SAndy Fiddaman 		{
83*906afcb8SAndy Fiddaman 			if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags)))
84*906afcb8SAndy Fiddaman 			{
85*906afcb8SAndy Fiddaman 				if (xr = (Write_f)dlsym(lp, "write"))
86*906afcb8SAndy Fiddaman 					wr = xr;
87*906afcb8SAndy Fiddaman 			}
88*906afcb8SAndy Fiddaman 		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
89*906afcb8SAndy Fiddaman 	}
90*906afcb8SAndy Fiddaman #endif
91*906afcb8SAndy Fiddaman 	if (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME))
92*906afcb8SAndy Fiddaman 	{
93*906afcb8SAndy Fiddaman 		do
94*906afcb8SAndy Fiddaman 		{
95*906afcb8SAndy Fiddaman 			if (lp = dllopen(strcmp(vp, "MAIN") ? vp : (char*)0, flags))
96*906afcb8SAndy Fiddaman 			{
97*906afcb8SAndy Fiddaman 				if (found)
98*906afcb8SAndy Fiddaman 				{
99*906afcb8SAndy Fiddaman 					b = e = 0;
100*906afcb8SAndy Fiddaman 					s = vp;
101*906afcb8SAndy Fiddaman 					for (;;)
102*906afcb8SAndy Fiddaman 					{
103*906afcb8SAndy Fiddaman 						switch (*s++)
104*906afcb8SAndy Fiddaman 						{
105*906afcb8SAndy Fiddaman 						case 0:
106*906afcb8SAndy Fiddaman 							break;
107*906afcb8SAndy Fiddaman 						case '/':
108*906afcb8SAndy Fiddaman 							b = s;
109*906afcb8SAndy Fiddaman 							e = 0;
110*906afcb8SAndy Fiddaman 							continue;
111*906afcb8SAndy Fiddaman 						case '.':
112*906afcb8SAndy Fiddaman 							if (!e)
113*906afcb8SAndy Fiddaman 								e = s - 1;
114*906afcb8SAndy Fiddaman 							continue;
115*906afcb8SAndy Fiddaman 						default:
116*906afcb8SAndy Fiddaman 							continue;
117*906afcb8SAndy Fiddaman 						}
118*906afcb8SAndy Fiddaman 						break;
119*906afcb8SAndy Fiddaman 					}
120*906afcb8SAndy Fiddaman 					if (b && e)
121*906afcb8SAndy Fiddaman 					{
122*906afcb8SAndy Fiddaman 						s = dummy;
123*906afcb8SAndy Fiddaman 						*s++ = '_';
124*906afcb8SAndy Fiddaman 						*s++ = '_';
125*906afcb8SAndy Fiddaman 						while (b < e)
126*906afcb8SAndy Fiddaman 							*s++ = *b++;
127*906afcb8SAndy Fiddaman 						b = "_dummy";
128*906afcb8SAndy Fiddaman 						while (*s++ = *b++);
129*906afcb8SAndy Fiddaman 						if (dlsym(lp, dummy))
130*906afcb8SAndy Fiddaman 						{
131*906afcb8SAndy Fiddaman 							dlclose(lp);
132*906afcb8SAndy Fiddaman 							lp = 0;
133*906afcb8SAndy Fiddaman 						}
134*906afcb8SAndy Fiddaman 					}
135*906afcb8SAndy Fiddaman 					if (lp)
136*906afcb8SAndy Fiddaman 					{
137*906afcb8SAndy Fiddaman #if DEBUG
138*906afcb8SAndy Fiddaman 						if (wr)
139*906afcb8SAndy Fiddaman 							(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp));
140*906afcb8SAndy Fiddaman #endif
141*906afcb8SAndy Fiddaman 						return lp;
142*906afcb8SAndy Fiddaman 					}
143*906afcb8SAndy Fiddaman #if DEBUG
144*906afcb8SAndy Fiddaman 					else if (wr)
145*906afcb8SAndy Fiddaman 						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp));
146*906afcb8SAndy Fiddaman #endif
147*906afcb8SAndy Fiddaman 				}
148*906afcb8SAndy Fiddaman 				else if ((_DLL_RLD_SYM_TYPE*)dlsym(lp, _DLL_RLD_SYM_STR) == here)
149*906afcb8SAndy Fiddaman 				{
150*906afcb8SAndy Fiddaman #if DEBUG
151*906afcb8SAndy Fiddaman 					if (wr)
152*906afcb8SAndy Fiddaman 						(*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp));
153*906afcb8SAndy Fiddaman #endif
154*906afcb8SAndy Fiddaman 					found = 1;
155*906afcb8SAndy Fiddaman 				}
156*906afcb8SAndy Fiddaman 			}
157*906afcb8SAndy Fiddaman 		} while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
158*906afcb8SAndy Fiddaman 	}
159*906afcb8SAndy Fiddaman 	return dllnext(flags);
160*906afcb8SAndy Fiddaman }
161*906afcb8SAndy Fiddaman 
162*906afcb8SAndy Fiddaman #endif
163*906afcb8SAndy Fiddaman 
164*906afcb8SAndy Fiddaman #ifndef RTLD_NEXT
165*906afcb8SAndy Fiddaman #if _dll_DYNAMIC
166*906afcb8SAndy Fiddaman 
167*906afcb8SAndy Fiddaman #include <link.h>
168*906afcb8SAndy Fiddaman 
169*906afcb8SAndy Fiddaman extern struct link_dynamic	_DYNAMIC;
170*906afcb8SAndy Fiddaman 
171*906afcb8SAndy Fiddaman #endif
172*906afcb8SAndy Fiddaman #endif
173*906afcb8SAndy Fiddaman 
174*906afcb8SAndy Fiddaman void*
dllnext(int flags)175*906afcb8SAndy Fiddaman dllnext(int flags)
176*906afcb8SAndy Fiddaman {
177*906afcb8SAndy Fiddaman 	register void*			dll;
178*906afcb8SAndy Fiddaman #ifndef RTLD_NEXT
179*906afcb8SAndy Fiddaman #if _dll_DYNAMIC
180*906afcb8SAndy Fiddaman 	register struct link_map*	map;
181*906afcb8SAndy Fiddaman 	register char*			s;
182*906afcb8SAndy Fiddaman 	register char*			b;
183*906afcb8SAndy Fiddaman #endif
184*906afcb8SAndy Fiddaman 	register char*			ver;
185*906afcb8SAndy Fiddaman 	char*				path;
186*906afcb8SAndy Fiddaman 
187*906afcb8SAndy Fiddaman 	static char			next[] = { _DLL_NEXT_PATH };
188*906afcb8SAndy Fiddaman #endif
189*906afcb8SAndy Fiddaman 
190*906afcb8SAndy Fiddaman #ifdef RTLD_NEXT
191*906afcb8SAndy Fiddaman 	dll = RTLD_NEXT;
192*906afcb8SAndy Fiddaman #else
193*906afcb8SAndy Fiddaman 	path = next;
194*906afcb8SAndy Fiddaman #if _dll_DYNAMIC
195*906afcb8SAndy Fiddaman 	for (map = _DYNAMIC.ld_un.ld_1->ld_loaded; map; map = map->lm_next)
196*906afcb8SAndy Fiddaman 	{
197*906afcb8SAndy Fiddaman 		b = 0;
198*906afcb8SAndy Fiddaman 		s = map->lm_name;
199*906afcb8SAndy Fiddaman 		while (*s)
200*906afcb8SAndy Fiddaman 			if (*s++ == '/')
201*906afcb8SAndy Fiddaman 				b = s;
202*906afcb8SAndy Fiddaman 		if (b && b[0] == 'l' && b[1] == 'i' && b[2] == 'b' && b[3] == 'c' && b[4] == '.')
203*906afcb8SAndy Fiddaman 		{
204*906afcb8SAndy Fiddaman 			path = map->lm_name;
205*906afcb8SAndy Fiddaman 			break;
206*906afcb8SAndy Fiddaman 		}
207*906afcb8SAndy Fiddaman 	}
208*906afcb8SAndy Fiddaman #endif
209*906afcb8SAndy Fiddaman 	ver = path + strlen(path);
210*906afcb8SAndy Fiddaman 	while (!(dll = dllopen(path, flags)))
211*906afcb8SAndy Fiddaman 	{
212*906afcb8SAndy Fiddaman 		do
213*906afcb8SAndy Fiddaman 		{
214*906afcb8SAndy Fiddaman 			if (ver <= path)
215*906afcb8SAndy Fiddaman 				return 0;
216*906afcb8SAndy Fiddaman 		} while (*--ver != '.');
217*906afcb8SAndy Fiddaman 		if (*(ver + 1) <= '0' || *(ver + 1) >= '9')
218*906afcb8SAndy Fiddaman 			return 0;
219*906afcb8SAndy Fiddaman 		*ver = 0;
220*906afcb8SAndy Fiddaman 	}
221*906afcb8SAndy Fiddaman #endif
222*906afcb8SAndy Fiddaman 	return dll;
223*906afcb8SAndy Fiddaman }
224