1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1997-2009 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* 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* 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