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