1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1997-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 56typedef ssize_t (*Write_f)(int, const void*, size_t); 57 58#endif 59 60#undef dllnext 61 62void* 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 169extern struct link_dynamic _DYNAMIC; 170 171#endif 172#endif 173 174void* 175dllnext(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