summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2010-10-25 20:34:45 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2010-10-25 20:34:45 +0000
commitdef90ce2d2284a29f73bcbc6f9a73cc494a7f24a (patch)
tree812fde735908a42f3bcac2f4578e032d0c881a8b /libexec
parentd539bcdfe39761e4307e30298b6dec05475521ef (diff)
Search loaded libs first and add support for SONAME matching. ok drahn@
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.so/library.c14
-rw-r--r--libexec/ld.so/library_mquery.c14
-rw-r--r--libexec/ld.so/library_subr.c108
-rw-r--r--libexec/ld.so/loader.c16
-rw-r--r--libexec/ld.so/resolve.c20
-rw-r--r--libexec/ld.so/resolve.h6
6 files changed, 128 insertions, 50 deletions
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index 0ddbb48293e..d8c3ba8c1ea 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.58 2008/10/02 20:12:08 kurt Exp $ */
+/* $OpenBSD: library.c,v 1.59 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -92,18 +92,6 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
#define ROUND_PG(x) (((x) + align) & ~(align))
#define TRUNC_PG(x) ((x) & ~(align))
- object = _dl_lookup_object(libname);
- if (object) {
- object->obj_flags |= flags & RTLD_GLOBAL;
- if (_dl_loading_object == NULL)
- _dl_loading_object = object;
- if (object->load_object != _dl_objects &&
- object->load_object != _dl_loading_object) {
- _dl_link_grpref(object->load_object, _dl_loading_object);
- }
- return(object); /* Already loaded */
- }
-
libfile = _dl_open(libname, O_RDONLY);
if (libfile < 0) {
_dl_errno = DL_CANT_OPEN;
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index cd0ea376426..13160933689 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.36 2008/10/02 20:12:08 kurt Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.37 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -98,18 +98,6 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
#define ROUND_PG(x) (((x) + align) & ~(align))
#define TRUNC_PG(x) ((x) & ~(align))
- object = _dl_lookup_object(libname);
- if (object) {
- object->obj_flags |= flags & RTLD_GLOBAL;
- if (_dl_loading_object == NULL)
- _dl_loading_object = object;
- if (object->load_object != _dl_objects &&
- object->load_object != _dl_loading_object) {
- _dl_link_grpref(object->load_object, _dl_loading_object);
- }
- return(object); /* Already loaded */
- }
-
libfile = _dl_open(libname, O_RDONLY);
if (libfile < 0) {
_dl_errno = DL_CANT_OPEN;
diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c
index 852e5c12233..29015e6e738 100644
--- a/libexec/ld.so/library_subr.c
+++ b/libexec/ld.so/library_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_subr.c,v 1.31 2010/07/01 19:25:44 drahn Exp $ */
+/* $OpenBSD: library_subr.c,v 1.32 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -59,11 +59,11 @@ struct dlochld _dlopened_child_list;
*/
int
-_dl_match_file(struct sod *sodp, char *name, int namelen)
+_dl_match_file(struct sod *sodp, const char *name, int namelen)
{
int match;
struct sod lsod;
- char *lname;
+ const char *lname;
lname = name;
if (sodp->sod_library) {
@@ -93,6 +93,35 @@ _dl_match_file(struct sod *sodp, char *name, int namelen)
return match;
}
+/*
+ * _dl_cmp_sod()
+ *
+ * This fucntion compares sod structs. The major must match exactly,
+ * and the minor must be same or larger.
+ *
+ * sodp is updated with the minor if this matches.
+ */
+
+int
+_dl_cmp_sod(struct sod *sodp, const struct sod *lsod)
+{
+ int match;
+
+ match = 1;
+ 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 = 0;
+
+ /* return version matched */
+ sodp->sod_major = lsod->sod_major;
+ sodp->sod_minor = lsod->sod_minor;
+ }
+ return match;
+}
+
char _dl_hint_store[MAXPATHLEN];
char *
@@ -227,8 +256,67 @@ nohints:
return NULL;
}
+elf_object_t *
+_dl_lookup_object(const char *req_name, struct sod *req_sod)
+{
+ elf_object_t *object = _dl_objects;
+
+ while (object) {
+ char *soname;
+
+ if (_dl_cmp_sod(req_sod, &object->sod) == 0)
+ return(object);
+
+ soname = (char *)object->Dyn.info[DT_SONAME];
+ if (soname != NULL) {
+ if (_dl_strcmp(req_name, soname) == 0)
+ return(object);
+ }
+
+ object = object->next;
+ }
+
+ return(NULL);
+}
+
+elf_object_t *
+_dl_find_loaded_shlib(const char *req_name, struct sod req_sod, int flags)
+{
+ elf_object_t *object;
+
+ object = _dl_lookup_object(req_name, &req_sod);
+
+ /* if not found retry with any minor */
+ if (object == NULL && req_sod.sod_library && req_sod.sod_minor != -1) {
+ short orig_minor = req_sod.sod_minor;
+ req_sod.sod_minor = -1;
+ object = _dl_lookup_object(req_name, &req_sod);
+
+ if (object != NULL && req_sod.sod_minor < orig_minor)
+ _dl_printf("warning: lib%s.so.%d.%d: "
+ "minor version >= %d expected, "
+ "using it anyway\n",
+ req_sod.sod_name, req_sod.sod_major,
+ req_sod.sod_minor, orig_minor);
+ }
+
+ if (object) { /* Already loaded */
+ object->obj_flags |= flags & RTLD_GLOBAL;
+ if (_dl_loading_object == NULL)
+ _dl_loading_object = object;
+ if (object->load_object != _dl_objects &&
+ object->load_object != _dl_loading_object) {
+ _dl_link_grpref(object->load_object, _dl_loading_object);
+ }
+ }
+
+ return (object);
+}
+
/*
* Load a shared object. Search order is:
+ * First check loaded objects for a matching shlib, otherwise:
+ *
* If the name contains a '/' use only the path preceding the
* library name and do not continue on to other methods if not
* found.
@@ -302,6 +390,12 @@ fullpathdone:
_dl_build_sod(libname, &sod);
req_sod = sod;
+ object = _dl_find_loaded_shlib(libname, req_sod, flags);
+ if (object) {
+ _dl_free((char *)sod.sod_name);
+ return (object);
+ }
+
again:
/* No '/' in name. Scan the known places, LD_LIBRARY_PATH first. */
if (_dl_libpath != NULL) {
@@ -345,8 +439,14 @@ done:
sod.sod_name, sod.sod_major,
req_sod.sod_minor, sod.sod_minor);
object = _dl_tryload_shlib(hint, type, flags);
+ if (object) {
+ object->sod = req_sod;
+ } else {
+ _dl_free((char *)sod.sod_name);
+ }
+ } else {
+ _dl_free((char *)sod.sod_name);
}
- _dl_free((char *)sod.sod_name);
return(object);
}
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 2fa77a8804a..275cbb28d25 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.119 2010/07/01 19:25:44 drahn Exp $ */
+/* $OpenBSD: loader.c,v 1.120 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -58,6 +58,7 @@ void _dl_setup_env(char **);
void _dl_dtors(void);
void _dl_boot_bind(const long, long *, Elf_Dyn *);
void _dl_fixup_user_env(void);
+void _dl_set_sod(const char *, struct sod *);
const char *_dl_progname;
int _dl_pagesz;
@@ -78,6 +79,17 @@ struct r_debug *_dl_debug_map;
void _dl_dopreload(char *paths);
void
+_dl_set_sod(const char *path, struct sod *sod)
+{
+ char *fname = _dl_strrchr(path, '/');
+
+ if (fname != NULL)
+ _dl_build_sod(++fname, sod);
+ else
+ _dl_build_sod(path, sod);
+}
+
+void
_dl_debug_state(void)
{
/* Debugger stub */
@@ -472,6 +484,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
exe_obj->load_list = load_list;
exe_obj->obj_flags |= RTLD_GLOBAL;
exe_obj->load_size = maxva - minva;
+ _dl_set_sod(exe_obj->load_name, &exe_obj->sod);
n = _dl_malloc(sizeof *n);
if (n == NULL)
@@ -501,6 +514,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
_dl_link_grpsym(dyn_obj, 1);
dyn_obj->status |= STAT_RELOC_DONE;
+ _dl_set_sod(dyn_obj->load_name, &dyn_obj->sod);
/*
* Everything should be in place now for doing the relocation
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 04da66f00c6..f77458c19a6 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.51 2010/08/11 01:14:27 drahn Exp $ */
+/* $OpenBSD: resolve.c,v 1.52 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -113,7 +113,7 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
if (object->Dyn.info[DT_RELA])
object->Dyn.info[DT_RELA] += obase;
if (object->Dyn.info[DT_SONAME])
- object->Dyn.info[DT_SONAME] += obase;
+ object->Dyn.info[DT_SONAME] += object->Dyn.info[DT_STRTAB];
if (object->Dyn.info[DT_RPATH])
object->Dyn.info[DT_RPATH] += object->Dyn.info[DT_STRTAB];
if (object->Dyn.info[DT_REL])
@@ -202,6 +202,8 @@ _dl_cleanup_objects()
while (head != NULL) {
if (head->load_name)
_dl_free(head->load_name);
+ if (head->sod.sod_name)
+ _dl_free((char *)head->sod.sod_name);
_dl_tailq_free(TAILQ_FIRST(&head->grpsym_list));
_dl_tailq_free(TAILQ_FIRST(&head->child_list));
_dl_tailq_free(TAILQ_FIRST(&head->grpref_list));
@@ -226,20 +228,6 @@ _dl_remove_object(elf_object_t *object)
}
-elf_object_t *
-_dl_lookup_object(const char *name)
-{
- elf_object_t *object;
-
- object = _dl_objects;
- while (object) {
- if (_dl_strcmp(name, object->load_name) == 0)
- return(object);
- object = object->next;
- }
- return(0);
-}
-
int _dl_find_symbol_obj(elf_object_t *object, const char *name,
unsigned long hash, int flags, const Elf_Sym **ref,
const Elf_Sym **weak_sym,
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index e6272c12747..977fa444619 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.61 2010/08/11 01:14:27 drahn Exp $ */
+/* $OpenBSD: resolve.h,v 1.62 2010/10/25 20:34:44 kurt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -136,6 +136,7 @@ struct elf_object {
/* object that caused this module to be loaded, used in symbol lookup */
elf_object_t *load_object;
+ struct sod sod;
void *prebind_data;
@@ -160,7 +161,6 @@ elf_object_t *_dl_finalize_object(const char *objname, Elf_Dyn *dynp,
void _dl_remove_object(elf_object_t *object);
void _dl_cleanup_objects(void);
-elf_object_t *_dl_lookup_object(const char *objname);
elf_object_t *_dl_load_shlib(const char *, elf_object_t *, int, int);
elf_object_t *_dl_tryload_shlib(const char *libname, int type, int flags);
@@ -220,7 +220,7 @@ void _dl_run_all_dtors(void);
/* Please don't rename; gdb(1) knows about this. */
Elf_Addr _dl_bind(elf_object_t *object, int index);
-int _dl_match_file(struct sod *sodp, char *name, int namelen);
+int _dl_match_file(struct sod *sodp, const char *name, int namelen);
char *_dl_find_shlib(struct sod *sodp, const char *searchpath, int nohints);
void _dl_load_list_free(struct load_list *load_list);