extern void* dllplug(const char* lib, const char* name, const char* ver, int flags, char* path, size_t size) { void* dll; int hit; Dllscan_t* dls; Dllent_t* dle; hit = 0; for (;;) { if (dls = dllsopen(lib, name, ver)) { while (dle = dllsread(dls)) { hit = 1; if (dll = dllopen(dle->path, flags|RTLD_GLOBAL|RTLD_PARENT)) { if (path && size) strncopy(path, dle->path, size); break; } else errorf("dll", NiL, 1, "%s: dlopen failed: %s", dle->path, dlerror()); } dllsclose(dls); } if (hit) return dll; if (!lib) break; lib = 0; } if ((dll = dllopen(name, flags)) && dll && path && size) strncopy(path, name, size); return dll; }
void *dllnext(int flags) { void *dll; #ifndef RTLD_NEXT #if _dll_DYNAMIC struct link_map *map; char *s; char *b; #endif char *ver; char *path; static char next[] = {_DLL_NEXT_PATH}; #endif #ifdef RTLD_NEXT UNUSED(flags); dll = RTLD_NEXT; #else path = next; #if _dll_DYNAMIC for (map = _DYNAMIC.ld_un.ld_1->ld_loaded; map; map = map->lm_next) { b = 0; s = map->lm_name; while (*s) { if (*s++ == '/') b = s; } if (b && b[0] == 'l' && b[1] == 'i' && b[2] == 'b' && b[3] == 'c' && b[4] == '.') { path = map->lm_name; break; } } #endif ver = path + strlen(path); while (!(dll = dllopen(path, flags))) { do { if (ver <= path) return 0; } while (*--ver != '.'); if (*(ver + 1) <= '0' || *(ver + 1) >= '9') return 0; *ver = 0; } #endif return dll; }
void *_dll_next(int flags, _DLL_RLD_SYM_TYPE *here) { char *vp; void *lp; int found = 0; char *s; char *b; char *e; char dummy[256]; #if DEBUG Write_f wr = 0; Write_f xr; char buf[1024]; #endif #if DEBUG if (getenv("DLL_DEBUG") && (vp = (char *)_rld_new_interface(_RLD_FIRST_PATHNAME))) { do { if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags))) { xr = (Write_f)dlsym(lp, "write") if (xr) wr = xr; } } while (vp = (char *)_rld_new_interface(_RLD_NEXT_PATHNAME)); } #endif vp = (char *)_rld_new_interface(_RLD_FIRST_PATHNAME); if (vp) { do { lp = dllopen(strcmp(vp, "MAIN") ? vp : NULL, flags); if (lp) { if (found) { b = e = 0; s = vp; for (;;) { switch (*s++) { case 0: break; case '/': b = s; e = 0; continue; case '.': if (!e) e = s - 1; continue; default: continue; } break; } if (b && e) { s = dummy; *s++ = '_'; *s++ = '_'; while (b < e) *s++ = *b++; b = "_dummy"; while (*s++ = *b++) ; if (dlsym(lp, dummy)) { dlclose(lp); lp = 0; } } if (lp) { #if DEBUG if (wr) (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp)); #endif return lp; } #if DEBUG else if (wr) { (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp)); } #endif } else if ((_DLL_RLD_SYM_TYPE *)dlsym(lp, _DLL_RLD_SYM_STR) == here) { #if DEBUG if (wr) (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp)); #endif found = 1; } } } while (vp = (char *)_rld_new_interface(_RLD_NEXT_PATHNAME)); } return dllnext(flags); }
extern void* dllplugin(const char* lib, const char* name, const char* ver, unsigned long rel, unsigned long* cur, int flags, char* path, size_t size) { void* dll; int err; int hit; Dllscan_t* dls; Dllent_t* dle; err = hit = 0; for (;;) { if (dls = dllsopen(lib, name, ver)) { while (dle = dllsread(dls)) { hit = 1; #if 0 again: #endif if (dll = dllopen(dle->path, flags|RTLD_GLOBAL|RTLD_PARENT)) { if (!dllcheck(dll, dle->path, rel, cur)) { err = state.error; dlclose(dll); dll = 0; continue; } if (path && size) strlcpy(path, dle->path, size); break; } else { #if 0 /* * dlopen() should load implicit libraries * this code does that * but it doesn't help on galadriel */ char* s; char* e; if ((s = dllerror(1)) && (e = strchr(s, ':'))) { *e = 0; error(1, "AHA %s implicit", s); dll = dllplugin(lib, s, 0, 0, 0, flags, path, size); *e = ':'; if (dll) { error(1, "AHA implicit %s => %s", s, path); goto again; } } #endif errorf("dll", NiL, 1, "dllplugin: %s dlopen failed: %s", dle->path, dllerror(1)); err = state.error; } } dllsclose(dls); } if (hit) { if (!dll) state.error = err; return dll; } if (!lib) break; lib = 0; } if (dll = dllopen(name, flags)) { if (!dllcheck(dll, name, rel, cur)) { dlclose(dll); dll = 0; } else if (path && size) strlcpy(path, name, size); } return dll; }