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