struct elf_resolve *_dl_load_shared_library(unsigned int rflags, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects) { char *pnt; struct elf_resolve *tpnt1; char *libname; _dl_internal_error_number = 0; libname = full_libname; /* quick hack to ensure mylibname buffer doesn't overflow. don't allow full_libname or any directory to be longer than 1024. */ if (_dl_strlen(full_libname) > 1024) goto goof; /* Skip over any initial initial './' and '/' stuff to * get the short form libname with no path garbage */ pnt = _dl_strrchr(libname, '/'); if (pnt) { libname = pnt + 1; } _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); /* If the filename has any '/', try it straight and leave it at that. For IBCS2 compatibility under linux, we substitute the string /usr/i486-sysv4/lib for /usr/lib in library names. */ if (libname != full_libname) { _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname); if (tpnt1) { return tpnt1; } } /* * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or * the default path of /usr/lib. Check in rpath directories. */ #ifdef __LDSO_RUNPATH__ pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL); if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, tpnt->libname)) != NULL) return tpnt1; } #endif #ifdef __LDSO_LD_LIBRARY_PATH__ /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt, NULL)) != NULL) { return tpnt1; } } #endif /* * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH. */ #ifdef __LDSO_RUNPATH__ pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL); if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL) return tpnt1; } #ifdef __LDSO_RUNPATH_OF_EXECUTABLE__ /* * Try the DT_RPATH of the executable itself. */ pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH]; if (pnt) { pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL) return tpnt1; } #endif #endif /* * Where should the cache be searched? There is no such concept in the * ABI, so we have some flexibility here. For now, search it before * the hard coded paths that follow (i.e before /lib and /usr/lib). */ #ifdef __LDSO_CACHE_SUPPORT__ if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) { int i; header_t *header = (header_t *) _dl_cache_addr; libentry_t *libent = (libentry_t *) & header[1]; char *strs = (char *) &libent[header->nlibs]; _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); for (i = 0; i < header->nlibs; i++) { if ((libent[i].flags == LIB_ELF || libent[i].flags == LIB_ELF_LIBC0 || libent[i].flags == LIB_ELF_LIBC5) && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset)) ) { return tpnt1; } } } #endif #ifdef LDSO_MULTILIB_DIR /* If multilib directory is selected, search it before falling back to standard lib directories. */ _dl_if_debug_dprint("\tsearching multilib lib path list\n"); tpnt1 = search_for_named_library(libname, rflags, UCLIBC_RUNTIME_PREFIX LDSO_MULTILIB_DIR ":" UCLIBC_RUNTIME_PREFIX "usr/" LDSO_MULTILIB_DIR, rpnt, NULL); if (tpnt1 != NULL) return tpnt1; #endif #if defined SHARED && defined __LDSO_SEARCH_INTERP_PATH__ /* Look for libraries wherever the shared library loader * was installed */ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt, NULL); if (tpnt1 != NULL) return tpnt1; #endif /* Lastly, search the standard list of paths for the library. This list must exactly match the list in uClibc/ldso/util/ldd.c */ _dl_if_debug_dprint("\tsearching full lib path list\n"); tpnt1 = search_for_named_library(libname, rflags, UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" #ifndef __LDSO_CACHE_SUPPORT__ ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" #endif , rpnt, NULL); if (tpnt1 != NULL) return tpnt1; #ifdef __LDSO_RUNPATH_OF_EXECUTABLE__ /* Very last resort, try the executable's DT_RUNPATH and DT_RPATH */ /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies * The set of directories specified by a given DT_RUNPATH entry is * used to find only the immediate dependencies of the executable or * shared object containing the DT_RUNPATH entry. That is, it is * used only for those dependencies contained in the DT_NEEDED * entries of the dynamic structure containing the DT_RUNPATH entry, * itself. One object's DT_RUNPATH entry does not affect the search * for any other object's dependencies. * * glibc (around 2.19) violates this and the usual suspects are * abusing this bug^Wrelaxed, user-friendly behaviour. */ pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RUNPATH]; if (pnt) { pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching exe's RUNPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL) return tpnt1; } pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH]; if (pnt) { pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL) return tpnt1; } #endif goof: /* Well, we shot our wad on that one. All we can do now is punt */ if (_dl_internal_error_number) _dl_error_number = _dl_internal_error_number; else _dl_error_number = LD_ERROR_NOFILE; _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname); return NULL; }
struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects) { char *pnt; struct elf_resolve *tpnt1; char *libname; _dl_internal_error_number = 0; libname = full_libname; /* quick hack to ensure mylibname buffer doesn't overflow. don't allow full_libname or any directory to be longer than 1024. */ if (_dl_strlen(full_libname) > 1024) goto goof; /* Skip over any initial initial './' and '/' stuff to * get the short form libname with no path garbage */ pnt = _dl_strrchr(libname, '/'); if (pnt) { libname = pnt + 1; } _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); /* If the filename has any '/', try it straight and leave it at that. For IBCS2 compatibility under linux, we substitute the string /usr/i486-sysv4/lib for /usr/lib in library names. */ if (libname != full_libname) { _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); if (tpnt1) { return tpnt1; } } /* * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or * the default path of /usr/lib. Check in rpath directories. */ #ifdef __LDSO_RUNPATH__ pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL); if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) return tpnt1; } #endif /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) { return tpnt1; } } /* * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH. */ #ifdef __LDSO_RUNPATH__ pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL); if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) return tpnt1; } #endif /* * Where should the cache be searched? There is no such concept in the * ABI, so we have some flexibility here. For now, search it before * the hard coded paths that follow (i.e before /lib and /usr/lib). */ #ifdef __LDSO_CACHE_SUPPORT__ if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) { int i; header_t *header = (header_t *) _dl_cache_addr; libentry_t *libent = (libentry_t *) & header[1]; char *strs = (char *) &libent[header->nlibs]; _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); for (i = 0; i < header->nlibs; i++) { if ((libent[i].flags == LIB_ELF || libent[i].flags == LIB_ELF_LIBC0 || libent[i].flags == LIB_ELF_LIBC5) && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset)) ) { return tpnt1; } } } #endif /* Look for libraries wherever the shared library loader * was installed */ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt); if (tpnt1 != NULL) return tpnt1; /* Lastly, search the standard list of paths for the library. This list must exactly match the list in uClibc/ldso/util/ldd.c */ _dl_if_debug_dprint("\tsearching full lib path list\n"); tpnt1 = search_for_named_library(libname, secure, UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" #ifndef __LDSO_CACHE_SUPPORT__ ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" #endif , rpnt); if (tpnt1 != NULL) return tpnt1; goof: /* Well, we shot our wad on that one. All we can do now is punt */ if (_dl_internal_error_number) _dl_error_number = _dl_internal_error_number; else _dl_error_number = LD_ERROR_NOFILE; _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname); return NULL; }