diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2005-03-23 19:48:06 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2005-03-23 19:48:06 +0000 |
commit | 3004e7060a61b8cd19902ea87d76783f0aa86144 (patch) | |
tree | 89de3b6a7b0f222e2297e1be89279be2a0ec4a9d | |
parent | 1a88b22742a7df6205d19a7ecf78aba3eda53a16 (diff) |
Code reorganization, move copied code in library.c and library_mquery.c
into its own file. no functional change.
-rw-r--r-- | libexec/ld.so/Makefile | 4 | ||||
-rw-r--r-- | libexec/ld.so/library.c | 322 | ||||
-rw-r--r-- | libexec/ld.so/library_mquery.c | 326 | ||||
-rw-r--r-- | libexec/ld.so/library_subr.c | 349 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 3 |
5 files changed, 358 insertions, 646 deletions
diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile index d1356d9949e..c65b116284b 100644 --- a/libexec/ld.so/Makefile +++ b/libexec/ld.so/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.24 2004/05/26 19:16:30 mickey Exp $ +# $OpenBSD: Makefile,v 1.25 2005/03/23 19:48:05 drahn Exp $ SUBDIR=ldconfig ldd VPATH=${.CURDIR}/../../lib/libc/string SRCS= ldasm.S loader.c resolve.c dlfcn.c dl_printf.c rtld_machine.c -SRCS+= util.c sod.c strsep.c strtol.c dir.c +SRCS+= util.c sod.c strsep.c strtol.c dir.c library_subr.c .if (${MACHINE_ARCH} == "i386") SRCS+= library_mquery.c .else diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c index 2026a8b3af2..a3c87d77e33 100644 --- a/libexec/ld.so/library.c +++ b/libexec/ld.so/library.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library.c,v 1.35 2004/10/17 03:56:49 drahn Exp $ */ +/* $OpenBSD: library.c,v 1.36 2005/03/23 19:48:05 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -30,314 +30,18 @@ #define _DYN_LOADER #include <sys/types.h> -#include <sys/syslimits.h> #include <sys/param.h> #include <fcntl.h> -#include <nlist.h> -#include <link.h> #include <sys/mman.h> -#include <dirent.h> #include "syscall.h" #include "archdep.h" #include "resolve.h" -#include "dir.h" -#include "sod.h" - -#define DEFAULT_PATH "/usr/lib" #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \ (((X) & PF_W) ? PROT_WRITE : 0) | \ (((X) & PF_X) ? PROT_EXEC : 0)) -static elf_object_t *_dl_tryload_shlib(const char *libname, int type); - -/* - * _dl_match_file() - * - * This fucntion determines if a given name matches what is specified - * in a struct sod. The major must match exactly, and the minor must - * be same or larger. - * - * sodp is updated with the minor if this matches. - */ - -int -_dl_match_file(struct sod *sodp, char *name, int namelen) -{ - int match; - struct sod lsod; - char *lname; - - lname = name; - if (sodp->sod_library) { - if (_dl_strncmp(name, "lib", 3)) - return 0; - lname += 3; - } - if (_dl_strncmp(lname, (char *)sodp->sod_name, - _dl_strlen((char *)sodp->sod_name))) - return 0; - - _dl_build_sod(name, &lsod); - - match = 0; - if ((_dl_strcmp((char *)lsod.sod_name, (char *)sodp->sod_name) == 0) && - (lsod.sod_library == sodp->sod_library) && - ((sodp->sod_major == -1) || (sodp->sod_major == lsod.sod_major)) && - ((sodp->sod_minor == -1) || - (lsod.sod_minor >= sodp->sod_minor))) { - match = 1; - - /* return version matched */ - sodp->sod_major = lsod.sod_major; - sodp->sod_minor = lsod.sod_minor; - } - _dl_free((char *)lsod.sod_name); - return match; -} - -char _dl_hint_store[MAXPATHLEN]; - -char * -_dl_find_shlib(struct sod *sodp, const char *searchpath, int nohints) -{ - char *hint, lp[PATH_MAX + 10], *path; - struct dirent *dp; - const char *pp; - int match, len; - DIR *dd; - struct sod tsod, bsod; /* transient and best sod */ - - /* if we are to search default directories, and hints - * are not to be used, search the standard path from ldconfig - * (_dl_hint_search_path) or use the default path - */ - if (nohints) - goto nohints; - - if (searchpath == NULL) { - /* search 'standard' locations, find any match in the hints */ - hint = _dl_findhint((char *)sodp->sod_name, sodp->sod_major, - sodp->sod_minor, NULL); - if (hint) - return hint; - } else { - /* search hints requesting matches for only - * the searchpath directories, - */ - pp = searchpath; - while (pp) { - path = lp; - while (path < lp + PATH_MAX && - *pp && *pp != ':' && *pp != ';') - *path++ = *pp++; - *path = 0; - - /* interpret "" as curdir "." */ - if (lp[0] == '\0') { - lp[0] = '.'; - lp[1] = '\0'; - } - - hint = _dl_findhint((char *)sodp->sod_name, - sodp->sod_major, sodp->sod_minor, lp); - if (hint != NULL) - return hint; - - if (*pp) /* Try curdir if ':' at end */ - pp++; - else - pp = 0; - } - } - - /* - * For each directory in the searchpath, read the directory - * entries looking for a match to sod. filename compare is - * done by _dl_match_file() - */ -nohints: - if (searchpath == NULL) { - if (_dl_hint_search_path != NULL) - searchpath = _dl_hint_search_path; - else - searchpath = DEFAULT_PATH; - } - pp = searchpath; - while (pp) { - path = lp; - while (path < lp + PATH_MAX && *pp && *pp != ':' && *pp != ';') - *path++ = *pp++; - *path = 0; - - /* interpret "" as curdir "." */ - if (lp[0] == '\0') { - lp[0] = '.'; - lp[1] = '\0'; - } - - if ((dd = _dl_opendir(lp)) != NULL) { - match = 0; - while ((dp = _dl_readdir(dd)) != NULL) { - tsod = *sodp; - if (_dl_match_file(&tsod, dp->d_name, - dp->d_namlen)) { - /* - * When a match is found, tsod is - * updated with the major+minor found. - * This version is compared with the - * largest so far (kept in bsod), - * and saved if larger. - */ - if (!match || - tsod.sod_major == -1 || - tsod.sod_major > bsod.sod_major || - ((tsod.sod_major == - bsod.sod_major) && - tsod.sod_minor > bsod.sod_minor)) { - bsod = tsod; - match = 1; - len = _dl_strlcpy( - _dl_hint_store, lp, - MAXPATHLEN); - if (lp[len-1] != '/') { - _dl_hint_store[len] = - '/'; - len++; - } - _dl_strlcpy( - &_dl_hint_store[len], - dp->d_name, - MAXPATHLEN-len); - if (tsod.sod_major == -1) - break; - } - } - } - _dl_closedir(dd); - if (match) { - *sodp = bsod; - return (_dl_hint_store); - } - } - - if (*pp) /* Try curdir if ':' at end */ - pp++; - else - pp = 0; - } - return NULL; -} - -/* - * Load a shared object. Search order is: - * If the name contains a '/' use the name exactly as is. (only) - * try the LD_LIBRARY_PATH specification (if present) - * search hints for match in LD_LIBRARY_PATH dirs - * this will only match specific libary version. - * search LD_LIBRARY_PATH dirs for match. - * this will find largest minor version in first dir found. - * check DT_RPATH paths, (if present) - * search hints for match in DT_RPATH dirs - * this will only match specific libary version. - * search DT_RPATH dirs for match. - * this will find largest minor version in first dir found. - * last look in default search directory, either as specified - * by ldconfig or default to '/usr/lib' - */ - -elf_object_t * -_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) -{ - int try_any_minor, ignore_hints; - struct sod sod, req_sod; - elf_object_t *object; - char *hint; - - try_any_minor = 0; - ignore_hints = 0; - - if (_dl_strchr(libname, '/')) { - object = _dl_tryload_shlib(libname, type); - return(object); - } - - _dl_build_sod(libname, &sod); - req_sod = sod; - -again: - /* - * No '/' in name. Scan the known places, LD_LIBRARY_PATH first. - */ - if (_dl_libpath != NULL) { - hint = _dl_find_shlib(&req_sod, _dl_libpath, ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return (object); - } - } - } - - /* - * Check DT_RPATH. - */ - if (parent->dyn.rpath != NULL) { - hint = _dl_find_shlib(&req_sod, parent->dyn.rpath, - ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return (object); - } - } - } - - /* check 'standard' locations */ - hint = _dl_find_shlib(&req_sod, NULL, ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return(object); - } - } - - if (try_any_minor == 0) { - try_any_minor = 1; - ignore_hints = 1; - req_sod.sod_minor = -1; - goto again; - } - _dl_free((char *)sod.sod_name); - _dl_errno = DL_NOT_FOUND; - return(0); -} - void _dl_load_list_free(struct load_list *load_list) { @@ -362,7 +66,7 @@ _dl_unload_shlib(elf_object_t *object) } -static elf_object_t * +elf_object_t * _dl_tryload_shlib(const char *libname, int type) { int libfile, i, align = _dl_pagesz - 1; @@ -527,25 +231,3 @@ _dl_tryload_shlib(const char *libname, int type) } return(object); } - -void -_dl_link_sub(elf_object_t *dep, elf_object_t *p) -{ - struct dep_node *n; - - n = _dl_malloc(sizeof *n); - if (n == NULL) - _dl_exit(5); - n->data = dep; - n->next_sibling = NULL; - if (p->first_child) { - p->last_child->next_sibling = n; - p->last_child = n; - } else - p->first_child = p->last_child = n; - - DL_DEB(("linking dep %s as child of %s\n", dep->load_name, - p->load_name)); -} - - diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c index 46139beda9e..2fa1165d627 100644 --- a/libexec/ld.so/library_mquery.c +++ b/libexec/ld.so/library_mquery.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library_mquery.c,v 1.15 2005/03/22 18:03:39 drahn Exp $ */ +/* $OpenBSD: library_mquery.c,v 1.16 2005/03/23 19:48:05 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -30,314 +30,18 @@ #define _DYN_LOADER #include <sys/types.h> -#include <sys/syslimits.h> #include <sys/param.h> #include <fcntl.h> -#include <nlist.h> -#include <link.h> #include <sys/mman.h> -#include <dirent.h> #include "syscall.h" #include "archdep.h" #include "resolve.h" -#include "dir.h" -#include "sod.h" - -#define DEFAULT_PATH "/usr/lib" #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \ (((X) & PF_W) ? PROT_WRITE : 0) | \ (((X) & PF_X) ? PROT_EXEC : 0)) -elf_object_t *_dl_tryload_shlib(const char *libname, int type); - -/* - * _dl_match_file() - * - * This fucntion determines if a given name matches what is specified - * in a struct sod. The major must match exactly, and the minor must - * be same or larger. - * - * sodp is updated with the minor if this matches. - */ - -int -_dl_match_file(struct sod *sodp, char *name, int namelen) -{ - int match; - struct sod lsod; - char *lname; - - lname = name; - if (sodp->sod_library) { - if (_dl_strncmp(name, "lib", 3)) - return 0; - lname += 3; - } - if (_dl_strncmp(lname, (char *)sodp->sod_name, - _dl_strlen((char *)sodp->sod_name))) - return 0; - - _dl_build_sod(name, &lsod); - - match = 0; - if ((_dl_strcmp((char *)lsod.sod_name, (char *)sodp->sod_name) == 0) && - (lsod.sod_library == sodp->sod_library) && - ((sodp->sod_major == -1) || (sodp->sod_major == lsod.sod_major)) && - ((sodp->sod_minor == -1) || - (lsod.sod_minor >= sodp->sod_minor))) { - match = 1; - - /* return version matched */ - sodp->sod_major = lsod.sod_major; - sodp->sod_minor = lsod.sod_minor; - } - _dl_free((char *)lsod.sod_name); - return match; -} - -char _dl_hint_store[MAXPATHLEN]; - -char * -_dl_find_shlib(struct sod *sodp, const char *searchpath, int nohints) -{ - char *hint, lp[PATH_MAX + 10], *path; - struct dirent *dp; - const char *pp; - int match, len; - DIR *dd; - struct sod tsod, bsod; /* transient and best sod */ - - /* if we are to search default directories, and hints - * are not to be used, search the standard path from ldconfig - * (_dl_hint_search_path) or use the default path - */ - if (nohints) - goto nohints; - - if (searchpath == NULL) { - /* search 'standard' locations, find any match in the hints */ - hint = _dl_findhint((char *)sodp->sod_name, sodp->sod_major, - sodp->sod_minor, NULL); - if (hint) - return hint; - } else { - /* search hints requesting matches for only - * the searchpath directories, - */ - pp = searchpath; - while (pp) { - path = lp; - while (path < lp + PATH_MAX && - *pp && *pp != ':' && *pp != ';') - *path++ = *pp++; - *path = 0; - - /* interpret "" as curdir "." */ - if (lp[0] == '\0') { - lp[0] = '.'; - lp[1] = '\0'; - } - - hint = _dl_findhint((char *)sodp->sod_name, - sodp->sod_major, sodp->sod_minor, lp); - if (hint != NULL) - return hint; - - if (*pp) /* Try curdir if ':' at end */ - pp++; - else - pp = 0; - } - } - - /* - * For each directory in the searchpath, read the directory - * entries looking for a match to sod. filename compare is - * done by _dl_match_file() - */ -nohints: - if (searchpath == NULL) { - if (_dl_hint_search_path != NULL) - searchpath = _dl_hint_search_path; - else - searchpath = DEFAULT_PATH; - } - pp = searchpath; - while (pp) { - path = lp; - while (path < lp + PATH_MAX && *pp && *pp != ':' && *pp != ';') - *path++ = *pp++; - *path = 0; - - /* interpret "" as curdir "." */ - if (lp[0] == '\0') { - lp[0] = '.'; - lp[1] = '\0'; - } - - if ((dd = _dl_opendir(lp)) != NULL) { - match = 0; - while ((dp = _dl_readdir(dd)) != NULL) { - tsod = *sodp; - if (_dl_match_file(&tsod, dp->d_name, - dp->d_namlen)) { - /* - * When a match is found, tsod is - * updated with the major+minor found. - * This version is compared with the - * largest so far (kept in bsod), - * and saved if larger. - */ - if (!match || - tsod.sod_major == -1 || - tsod.sod_major > bsod.sod_major || - ((tsod.sod_major == - bsod.sod_major) && - tsod.sod_minor > bsod.sod_minor)) { - bsod = tsod; - match = 1; - len = _dl_strlcpy( - _dl_hint_store, lp, - MAXPATHLEN); - if (lp[len-1] != '/') { - _dl_hint_store[len] = - '/'; - len++; - } - _dl_strlcpy( - &_dl_hint_store[len], - dp->d_name, - MAXPATHLEN-len); - if (tsod.sod_major == -1) - break; - } - } - } - _dl_closedir(dd); - if (match) { - *sodp = bsod; - return (_dl_hint_store); - } - } - - if (*pp) /* Try curdir if ':' at end */ - pp++; - else - pp = 0; - } - return NULL; -} - -/* - * Load a shared object. Search order is: - * If the name contains a '/' use the name exactly as is. (only) - * try the LD_LIBRARY_PATH specification (if present) - * search hints for match in LD_LIBRARY_PATH dirs - * this will only match specific libary version. - * search LD_LIBRARY_PATH dirs for match. - * this will find largest minor version in first dir found. - * check DT_RPATH paths, (if present) - * search hints for match in DT_RPATH dirs - * this will only match specific libary version. - * search DT_RPATH dirs for match. - * this will find largest minor version in first dir found. - * last look in default search directory, either as specified - * by ldconfig or default to '/usr/lib' - */ - -elf_object_t * -_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) -{ - int try_any_minor, ignore_hints; - struct sod sod, req_sod; - elf_object_t *object; - char *hint; - - try_any_minor = 0; - ignore_hints = 0; - - if (_dl_strchr(libname, '/')) { - object = _dl_tryload_shlib(libname, type); - return(object); - } - - _dl_build_sod(libname, &sod); - req_sod = sod; - -again: - /* - * No '/' in name. Scan the known places, LD_LIBRARY_PATH first. - */ - if (_dl_libpath != NULL) { - hint = _dl_find_shlib(&req_sod, _dl_libpath, ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return (object); - } - } - } - - /* - * Check DT_RPATH. - */ - if (parent->dyn.rpath != NULL) { - hint = _dl_find_shlib(&req_sod, parent->dyn.rpath, - ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return (object); - } - } - } - - /* check 'standard' locations */ - hint = _dl_find_shlib(&req_sod, NULL, ignore_hints); - if (hint != NULL) { - if (req_sod.sod_minor < sod.sod_minor) - _dl_printf("warning: lib%s.so.%d.%d: " - "minor version >= %d expected, " - "using it anyway\n", - sod.sod_name, sod.sod_major, - req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type); - if (object != NULL) { - _dl_free((char *)sod.sod_name); - object->obj_flags = flags; - return(object); - } - } - - if (try_any_minor == 0) { - try_any_minor = 1; - ignore_hints = 1; - req_sod.sod_minor = -1; - goto again; - } - _dl_free((char *)sod.sod_name); - _dl_errno = DL_NOT_FOUND; - return(0); -} - void _dl_load_list_free(struct load_list *load_list) { @@ -354,8 +58,6 @@ _dl_load_list_free(struct load_list *load_list) } } -void _dl_run_dtors(elf_object_t *object); - void _dl_unload_shlib(elf_object_t *object) { @@ -381,7 +83,7 @@ _dl_tryload_shlib(const char *libname, int type) int size; Elf_Addr load_end = 0; struct stat sb; - + #define ROUND_PG(x) (((x) + align) & ~(align)) #define TRUNC_PG(x) ((x) & ~(align)) @@ -409,7 +111,7 @@ _dl_tryload_shlib(const char *libname, int type) return(object); } } - + _dl_read(libfile, hbuf, sizeof(hbuf)); ehdr = (Elf_Ehdr *)hbuf; if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 || @@ -572,25 +274,3 @@ fail: _dl_load_list_free(lowld); return(0); } - -void -_dl_link_sub(elf_object_t *dep, elf_object_t *p) -{ - struct dep_node *n; - - n = _dl_malloc(sizeof *n); - if (n == NULL) - _dl_exit(5); - n->data = dep; - n->next_sibling = NULL; - if (p->first_child) { - p->last_child->next_sibling = n; - p->last_child = n; - } else - p->first_child = p->last_child = n; - - DL_DEB(("linking dep %s as child of %s\n", dep->load_name, - p->load_name)); -} - - diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c new file mode 100644 index 00000000000..b50afda6063 --- /dev/null +++ b/libexec/ld.so/library_subr.c @@ -0,0 +1,349 @@ +/* $OpenBSD: library_subr.c,v 1.1 2005/03/23 19:48:05 drahn Exp $ */ + +/* + * Copyright (c) 2002 Dale Rahn + * Copyright (c) 1998 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define _DYN_LOADER + +#include <sys/types.h> +#include <sys/syslimits.h> +#include <sys/param.h> +#include <dirent.h> + +#include "archdep.h" +#include "resolve.h" +#include "dir.h" +#include "sod.h" + +#define DEFAULT_PATH "/usr/lib" + +/* + * _dl_match_file() + * + * This fucntion determines if a given name matches what is specified + * in a struct sod. The major must match exactly, and the minor must + * be same or larger. + * + * sodp is updated with the minor if this matches. + */ + +int +_dl_match_file(struct sod *sodp, char *name, int namelen) +{ + int match; + struct sod lsod; + char *lname; + + lname = name; + if (sodp->sod_library) { + if (_dl_strncmp(name, "lib", 3)) + return 0; + lname += 3; + } + if (_dl_strncmp(lname, (char *)sodp->sod_name, + _dl_strlen((char *)sodp->sod_name))) + return 0; + + _dl_build_sod(name, &lsod); + + match = 0; + if ((_dl_strcmp((char *)lsod.sod_name, (char *)sodp->sod_name) == 0) && + (lsod.sod_library == sodp->sod_library) && + ((sodp->sod_major == -1) || (sodp->sod_major == lsod.sod_major)) && + ((sodp->sod_minor == -1) || + (lsod.sod_minor >= sodp->sod_minor))) { + match = 1; + + /* return version matched */ + sodp->sod_major = lsod.sod_major; + sodp->sod_minor = lsod.sod_minor; + } + _dl_free((char *)lsod.sod_name); + return match; +} + +char _dl_hint_store[MAXPATHLEN]; + +char * +_dl_find_shlib(struct sod *sodp, const char *searchpath, int nohints) +{ + char *hint, lp[PATH_MAX + 10], *path; + struct dirent *dp; + const char *pp; + int match, len; + DIR *dd; + struct sod tsod, bsod; /* transient and best sod */ + + /* if we are to search default directories, and hints + * are not to be used, search the standard path from ldconfig + * (_dl_hint_search_path) or use the default path + */ + if (nohints) + goto nohints; + + if (searchpath == NULL) { + /* search 'standard' locations, find any match in the hints */ + hint = _dl_findhint((char *)sodp->sod_name, sodp->sod_major, + sodp->sod_minor, NULL); + if (hint) + return hint; + } else { + /* search hints requesting matches for only + * the searchpath directories, + */ + pp = searchpath; + while (pp) { + path = lp; + while (path < lp + PATH_MAX && + *pp && *pp != ':' && *pp != ';') + *path++ = *pp++; + *path = 0; + + /* interpret "" as curdir "." */ + if (lp[0] == '\0') { + lp[0] = '.'; + lp[1] = '\0'; + } + + hint = _dl_findhint((char *)sodp->sod_name, + sodp->sod_major, sodp->sod_minor, lp); + if (hint != NULL) + return hint; + + if (*pp) /* Try curdir if ':' at end */ + pp++; + else + pp = 0; + } + } + + /* + * For each directory in the searchpath, read the directory + * entries looking for a match to sod. filename compare is + * done by _dl_match_file() + */ +nohints: + if (searchpath == NULL) { + if (_dl_hint_search_path != NULL) + searchpath = _dl_hint_search_path; + else + searchpath = DEFAULT_PATH; + } + pp = searchpath; + while (pp) { + path = lp; + while (path < lp + PATH_MAX && *pp && *pp != ':' && *pp != ';') + *path++ = *pp++; + *path = 0; + + /* interpret "" as curdir "." */ + if (lp[0] == '\0') { + lp[0] = '.'; + lp[1] = '\0'; + } + + if ((dd = _dl_opendir(lp)) != NULL) { + match = 0; + while ((dp = _dl_readdir(dd)) != NULL) { + tsod = *sodp; + if (_dl_match_file(&tsod, dp->d_name, + dp->d_namlen)) { + /* + * When a match is found, tsod is + * updated with the major+minor found. + * This version is compared with the + * largest so far (kept in bsod), + * and saved if larger. + */ + if (!match || + tsod.sod_major == -1 || + tsod.sod_major > bsod.sod_major || + ((tsod.sod_major == + bsod.sod_major) && + tsod.sod_minor > bsod.sod_minor)) { + bsod = tsod; + match = 1; + len = _dl_strlcpy( + _dl_hint_store, lp, + MAXPATHLEN); + if (lp[len-1] != '/') { + _dl_hint_store[len] = + '/'; + len++; + } + _dl_strlcpy( + &_dl_hint_store[len], + dp->d_name, + MAXPATHLEN-len); + if (tsod.sod_major == -1) + break; + } + } + } + _dl_closedir(dd); + if (match) { + *sodp = bsod; + return (_dl_hint_store); + } + } + + if (*pp) /* Try curdir if ':' at end */ + pp++; + else + pp = 0; + } + return NULL; +} + +/* + * Load a shared object. Search order is: + * If the name contains a '/' use the name exactly as is. (only) + * try the LD_LIBRARY_PATH specification (if present) + * search hints for match in LD_LIBRARY_PATH dirs + * this will only match specific libary version. + * search LD_LIBRARY_PATH dirs for match. + * this will find largest minor version in first dir found. + * check DT_RPATH paths, (if present) + * search hints for match in DT_RPATH dirs + * this will only match specific libary version. + * search DT_RPATH dirs for match. + * this will find largest minor version in first dir found. + * last look in default search directory, either as specified + * by ldconfig or default to '/usr/lib' + */ + +elf_object_t * +_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) +{ + int try_any_minor, ignore_hints; + struct sod sod, req_sod; + elf_object_t *object; + char *hint; + + try_any_minor = 0; + ignore_hints = 0; + + if (_dl_strchr(libname, '/')) { + object = _dl_tryload_shlib(libname, type); + return(object); + } + + _dl_build_sod(libname, &sod); + req_sod = sod; + +again: + /* + * No '/' in name. Scan the known places, LD_LIBRARY_PATH first. + */ + if (_dl_libpath != NULL) { + hint = _dl_find_shlib(&req_sod, _dl_libpath, ignore_hints); + if (hint != NULL) { + if (req_sod.sod_minor < sod.sod_minor) + _dl_printf("warning: lib%s.so.%d.%d: " + "minor version >= %d expected, " + "using it anyway\n", + sod.sod_name, sod.sod_major, + req_sod.sod_minor, sod.sod_minor); + object = _dl_tryload_shlib(hint, type); + if (object != NULL) { + _dl_free((char *)sod.sod_name); + object->obj_flags = flags; + return (object); + } + } + } + + /* + * Check DT_RPATH. + */ + if (parent->dyn.rpath != NULL) { + hint = _dl_find_shlib(&req_sod, parent->dyn.rpath, + ignore_hints); + if (hint != NULL) { + if (req_sod.sod_minor < sod.sod_minor) + _dl_printf("warning: lib%s.so.%d.%d: " + "minor version >= %d expected, " + "using it anyway\n", + sod.sod_name, sod.sod_major, + req_sod.sod_minor, sod.sod_minor); + object = _dl_tryload_shlib(hint, type); + if (object != NULL) { + _dl_free((char *)sod.sod_name); + object->obj_flags = flags; + return (object); + } + } + } + + /* check 'standard' locations */ + hint = _dl_find_shlib(&req_sod, NULL, ignore_hints); + if (hint != NULL) { + if (req_sod.sod_minor < sod.sod_minor) + _dl_printf("warning: lib%s.so.%d.%d: " + "minor version >= %d expected, " + "using it anyway\n", + sod.sod_name, sod.sod_major, + req_sod.sod_minor, sod.sod_minor); + object = _dl_tryload_shlib(hint, type); + if (object != NULL) { + _dl_free((char *)sod.sod_name); + object->obj_flags = flags; + return(object); + } + } + + if (try_any_minor == 0) { + try_any_minor = 1; + ignore_hints = 1; + req_sod.sod_minor = -1; + goto again; + } + _dl_free((char *)sod.sod_name); + _dl_errno = DL_NOT_FOUND; + return(0); +} + + +void +_dl_link_sub(elf_object_t *dep, elf_object_t *p) +{ + struct dep_node *n; + + n = _dl_malloc(sizeof *n); + if (n == NULL) + _dl_exit(5); + n->data = dep; + n->next_sibling = NULL; + if (p->first_child) { + p->last_child->next_sibling = n; + p->last_child = n; + } else + p->first_child = p->last_child = n; + + DL_DEB(("linking dep %s as child of %s\n", dep->load_name, + p->load_name)); +} diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 32bc4fa06ba..1f583fe23ad 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.32 2004/08/11 19:14:56 drahn Exp $ */ +/* $OpenBSD: resolve.h,v 1.33 2005/03/23 19:48:05 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -143,6 +143,7 @@ extern void _dl_remove_object(elf_object_t *object); extern elf_object_t *_dl_lookup_object(const char *objname); extern elf_object_t *_dl_load_shlib(const char *, elf_object_t *, int, int); extern void _dl_unload_shlib(elf_object_t *object); +elf_object_t *_dl_tryload_shlib(const char *libname, int type); extern int _dl_md_reloc(elf_object_t *object, int rel, int relsz); extern void _dl_md_reloc_got(elf_object_t *object, int lazy); |