diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2010-10-25 20:34:45 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2010-10-25 20:34:45 +0000 |
commit | def90ce2d2284a29f73bcbc6f9a73cc494a7f24a (patch) | |
tree | 812fde735908a42f3bcac2f4578e032d0c881a8b /libexec | |
parent | d539bcdfe39761e4307e30298b6dec05475521ef (diff) |
Search loaded libs first and add support for SONAME matching. ok drahn@
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/library.c | 14 | ||||
-rw-r--r-- | libexec/ld.so/library_mquery.c | 14 | ||||
-rw-r--r-- | libexec/ld.so/library_subr.c | 108 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 16 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 20 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 6 |
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); |