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