summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2005-03-23 19:48:06 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2005-03-23 19:48:06 +0000
commit3004e7060a61b8cd19902ea87d76783f0aa86144 (patch)
tree89de3b6a7b0f222e2297e1be89279be2a0ec4a9d
parent1a88b22742a7df6205d19a7ecf78aba3eda53a16 (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/Makefile4
-rw-r--r--libexec/ld.so/library.c322
-rw-r--r--libexec/ld.so/library_mquery.c326
-rw-r--r--libexec/ld.so/library_subr.c349
-rw-r--r--libexec/ld.so/resolve.h3
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);