From 51ff0f67c733ac9dd1ad405978fe1d7f1141c250 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Sat, 11 Aug 2001 04:08:41 +0000 Subject: Fix the library searching routine so it is way simpler, and so it matches the routine in ldd.c --- ldso/ldso/dl-elf.c | 201 +++++++++++++++++------------------------------- ldso/ldso/ld_string.h | 17 +++- ldso/ldso/readelflib1.c | 201 +++++++++++++++++------------------------------- ldso/ldso/string.h | 17 +++- 4 files changed, 170 insertions(+), 266 deletions(-) (limited to 'ldso') diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 75acde927..eed74321d 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -118,6 +118,49 @@ int _dl_unmap_cache(void) #endif +/* This function's behavior must exactly match that + * in uClibc/ldso/util/ldd.c */ +static struct elf_resolve * +search_for_named_library(char *name, int secure, const char *path_list) +{ + int i, count = 0; + char *path, *path_n; + char mylibname[2050]; + struct elf_resolve *tpnt1; + + + /* We need a writable copy of this string */ + path = _dl_strdup(path_list); + if (!path) { + _dl_dprintf(2, "Out of memory!\n"); + _dl_exit(0); + } + + + /* Unlike ldd.c, don't bother to eliminate double //s */ + + + /* Replace colons with zeros in path_list and count them */ + for(i=_dl_strlen(path); i > 0; i--) { + if (path[i]==':') { + path[i]=0; + count++; + } + } + + path_n = path; + for (i = 0; i < count; i++) { + _dl_strcpy(mylibname, path_n); + _dl_strcat(mylibname, "/"); + _dl_strcat(mylibname, name); + if ((tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0)) != NULL) + return tpnt1; + path_n += (_dl_strlen(path_n) + 1); + } + return NULL; +} + + /* * Used to return error codes back to dlopen et. al. */ @@ -128,9 +171,8 @@ unsigned long _dl_internal_error_number; struct elf_resolve *_dl_load_shared_library(int secure, struct elf_resolve *tpnt, char *full_libname) { - char *pnt, *pnt1, *pnt2; - struct elf_resolve *tpnt1 = NULL; - char mylibname[2050]; + char *pnt; + struct elf_resolve *tpnt1; char *libname; _dl_internal_error_number = 0; @@ -160,71 +202,30 @@ struct elf_resolve *_dl_load_shared_library(int secure, /* * The ABI specifies that RPATH is searched before LD_*_PATH or - * the default path of /usr/lib. - * Check in rpath directories + * the default path of /usr/lib. Check in rpath directories. */ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { if (tpnt->libtype == elf_executable) { - pnt1 = (char *) tpnt->dynamic_info[DT_RPATH]; - if (pnt1) { - pnt1 += (unsigned long) tpnt->loadaddr + + pnt = (char *) tpnt->dynamic_info[DT_RPATH]; + if (pnt) { + pnt += (unsigned long) tpnt->loadaddr + tpnt->dynamic_info[DT_STRTAB]; - while (*pnt1) { - pnt2 = mylibname; - while (*pnt1 && *pnt1 != ':') { - if (pnt2 - mylibname < 1024) - *pnt2++ = *pnt1++; - else - pnt1++; - } - if (pnt2 - mylibname >= 1024) - break; - if (pnt2[-1] != '/') - *pnt2++ = '/'; - pnt = libname; - while (*pnt) - *pnt2++ = *pnt++; - *pnt2++ = 0; - tpnt1 = - _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - if (*pnt1 == ':') - pnt1++; + if ((tpnt1 = search_for_named_library(libname, secure, pnt)) != NULL) + { + return tpnt1; } } } } - /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ - pnt1 = _dl_library_path; - if (pnt1 && *pnt1) { - while (*pnt1) { - pnt2 = mylibname; - while (*pnt1 && *pnt1 != ':' && *pnt1 != ';') { - if (pnt2 - mylibname < 1024) - *pnt2++ = *pnt1++; - else - pnt1++; - } - if (pnt2 - mylibname >= 1024) - break; - if (pnt2[-1] != '/') - *pnt2++ = '/'; - pnt = libname; - while (*pnt) - *pnt2++ = *pnt++; - *pnt2++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - if (*pnt1 == ':' || *pnt1 == ';') - pnt1++; - } + if (_dl_library_path) { + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path)) != NULL) + { + return tpnt1; + } } - /* * 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 @@ -248,83 +249,19 @@ struct elf_resolve *_dl_load_shared_library(int secure, } #endif - /* Check in /usr/lib */ - pnt1 = UCLIBC_TARGET_PREFIX "/usr/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Check in /lib */ - pnt1 = UCLIBC_TARGET_PREFIX "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Bummer. Nothing so far. Try /lib */ - pnt1 = UCLIBC_DEVEL_PREFIX "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Still nothing... Ok, try /lib */ - pnt1 = UCLIBC_BUILD_DIR "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Wow. Still nothing. Try /usr/lib */ - pnt1 = "/usr/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* This is our last hope before giving up -- Try /lib */ - pnt1 = "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/util/ldd.c */ + if ((tpnt1 = search_for_named_library(libname, secure, + UCLIBC_TARGET_PREFIX "/usr/lib:" + UCLIBC_TARGET_PREFIX "/lib:" + UCLIBC_DEVEL_PREFIX "/lib:" + UCLIBC_BUILD_DIR "/lib:" + "/usr/lib:" + "/lib") + ) != NULL) + { return tpnt1; + } goof: /* Well, we shot our wad on that one. All we can do now is punt */ diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h index fcdb8768b..b94b1c5f9 100644 --- a/ldso/ldso/ld_string.h +++ b/ldso/ldso/ld_string.h @@ -11,6 +11,7 @@ extern void _dl_dprintf(int, const char *, ...); static size_t _dl_strlen(const char * str); +static char *_dl_strcat(char *dst, const char *src); static char * _dl_strcpy(char * dst,const char *src); static int _dl_strcmp(const char * s1,const char * s2); static int _dl_strncmp(const char * s1,const char * s2,size_t len); @@ -18,7 +19,7 @@ static char * _dl_strchr(const char * str,int c); static char *_dl_strrchr(const char *str, int c); static void * _dl_memcpy(void * dst, const void * src, size_t len); static int _dl_memcmp(const void * s1,const void * s2,size_t len); -static void * _dl_memset(void * str,int c,size_t len); +static void *_dl_memset(void * str,int c,size_t len); static char *_dl_get_last_path_component(char *path); static char *_dl_simple_ltoa(char * local, unsigned long i); static char *_dl_simple_ltoahex(char * local, unsigned long i); @@ -36,6 +37,20 @@ static inline size_t _dl_strlen(const char * str) return (ptr - str); } +static inline char *_dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst; + + while (*ptr) + ptr++; + + while (*src) + *ptr++ = *src++; + *ptr = '\0'; + + return dst; +} + static inline char * _dl_strcpy(char * dst,const char *src) { register char *ptr = dst; diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index 75acde927..eed74321d 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -118,6 +118,49 @@ int _dl_unmap_cache(void) #endif +/* This function's behavior must exactly match that + * in uClibc/ldso/util/ldd.c */ +static struct elf_resolve * +search_for_named_library(char *name, int secure, const char *path_list) +{ + int i, count = 0; + char *path, *path_n; + char mylibname[2050]; + struct elf_resolve *tpnt1; + + + /* We need a writable copy of this string */ + path = _dl_strdup(path_list); + if (!path) { + _dl_dprintf(2, "Out of memory!\n"); + _dl_exit(0); + } + + + /* Unlike ldd.c, don't bother to eliminate double //s */ + + + /* Replace colons with zeros in path_list and count them */ + for(i=_dl_strlen(path); i > 0; i--) { + if (path[i]==':') { + path[i]=0; + count++; + } + } + + path_n = path; + for (i = 0; i < count; i++) { + _dl_strcpy(mylibname, path_n); + _dl_strcat(mylibname, "/"); + _dl_strcat(mylibname, name); + if ((tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0)) != NULL) + return tpnt1; + path_n += (_dl_strlen(path_n) + 1); + } + return NULL; +} + + /* * Used to return error codes back to dlopen et. al. */ @@ -128,9 +171,8 @@ unsigned long _dl_internal_error_number; struct elf_resolve *_dl_load_shared_library(int secure, struct elf_resolve *tpnt, char *full_libname) { - char *pnt, *pnt1, *pnt2; - struct elf_resolve *tpnt1 = NULL; - char mylibname[2050]; + char *pnt; + struct elf_resolve *tpnt1; char *libname; _dl_internal_error_number = 0; @@ -160,71 +202,30 @@ struct elf_resolve *_dl_load_shared_library(int secure, /* * The ABI specifies that RPATH is searched before LD_*_PATH or - * the default path of /usr/lib. - * Check in rpath directories + * the default path of /usr/lib. Check in rpath directories. */ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { if (tpnt->libtype == elf_executable) { - pnt1 = (char *) tpnt->dynamic_info[DT_RPATH]; - if (pnt1) { - pnt1 += (unsigned long) tpnt->loadaddr + + pnt = (char *) tpnt->dynamic_info[DT_RPATH]; + if (pnt) { + pnt += (unsigned long) tpnt->loadaddr + tpnt->dynamic_info[DT_STRTAB]; - while (*pnt1) { - pnt2 = mylibname; - while (*pnt1 && *pnt1 != ':') { - if (pnt2 - mylibname < 1024) - *pnt2++ = *pnt1++; - else - pnt1++; - } - if (pnt2 - mylibname >= 1024) - break; - if (pnt2[-1] != '/') - *pnt2++ = '/'; - pnt = libname; - while (*pnt) - *pnt2++ = *pnt++; - *pnt2++ = 0; - tpnt1 = - _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - if (*pnt1 == ':') - pnt1++; + if ((tpnt1 = search_for_named_library(libname, secure, pnt)) != NULL) + { + return tpnt1; } } } } - /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ - pnt1 = _dl_library_path; - if (pnt1 && *pnt1) { - while (*pnt1) { - pnt2 = mylibname; - while (*pnt1 && *pnt1 != ':' && *pnt1 != ';') { - if (pnt2 - mylibname < 1024) - *pnt2++ = *pnt1++; - else - pnt1++; - } - if (pnt2 - mylibname >= 1024) - break; - if (pnt2[-1] != '/') - *pnt2++ = '/'; - pnt = libname; - while (*pnt) - *pnt2++ = *pnt++; - *pnt2++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - if (*pnt1 == ':' || *pnt1 == ';') - pnt1++; - } + if (_dl_library_path) { + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path)) != NULL) + { + return tpnt1; + } } - /* * 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 @@ -248,83 +249,19 @@ struct elf_resolve *_dl_load_shared_library(int secure, } #endif - /* Check in /usr/lib */ - pnt1 = UCLIBC_TARGET_PREFIX "/usr/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Check in /lib */ - pnt1 = UCLIBC_TARGET_PREFIX "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Bummer. Nothing so far. Try /lib */ - pnt1 = UCLIBC_DEVEL_PREFIX "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Still nothing... Ok, try /lib */ - pnt1 = UCLIBC_BUILD_DIR "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* Wow. Still nothing. Try /usr/lib */ - pnt1 = "/usr/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) - return tpnt1; - - /* This is our last hope before giving up -- Try /lib */ - pnt1 = "/lib/"; - pnt = mylibname; - while (*pnt1) - *pnt++ = *pnt1++; - pnt1 = libname; - while (*pnt1) - *pnt++ = *pnt1++; - *pnt++ = 0; - tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0); - if (tpnt1) + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/util/ldd.c */ + if ((tpnt1 = search_for_named_library(libname, secure, + UCLIBC_TARGET_PREFIX "/usr/lib:" + UCLIBC_TARGET_PREFIX "/lib:" + UCLIBC_DEVEL_PREFIX "/lib:" + UCLIBC_BUILD_DIR "/lib:" + "/usr/lib:" + "/lib") + ) != NULL) + { return tpnt1; + } goof: /* Well, we shot our wad on that one. All we can do now is punt */ diff --git a/ldso/ldso/string.h b/ldso/ldso/string.h index fcdb8768b..b94b1c5f9 100644 --- a/ldso/ldso/string.h +++ b/ldso/ldso/string.h @@ -11,6 +11,7 @@ extern void _dl_dprintf(int, const char *, ...); static size_t _dl_strlen(const char * str); +static char *_dl_strcat(char *dst, const char *src); static char * _dl_strcpy(char * dst,const char *src); static int _dl_strcmp(const char * s1,const char * s2); static int _dl_strncmp(const char * s1,const char * s2,size_t len); @@ -18,7 +19,7 @@ static char * _dl_strchr(const char * str,int c); static char *_dl_strrchr(const char *str, int c); static void * _dl_memcpy(void * dst, const void * src, size_t len); static int _dl_memcmp(const void * s1,const void * s2,size_t len); -static void * _dl_memset(void * str,int c,size_t len); +static void *_dl_memset(void * str,int c,size_t len); static char *_dl_get_last_path_component(char *path); static char *_dl_simple_ltoa(char * local, unsigned long i); static char *_dl_simple_ltoahex(char * local, unsigned long i); @@ -36,6 +37,20 @@ static inline size_t _dl_strlen(const char * str) return (ptr - str); } +static inline char *_dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst; + + while (*ptr) + ptr++; + + while (*src) + *ptr++ = *src++; + *ptr = '\0'; + + return dst; +} + static inline char * _dl_strcpy(char * dst,const char *src) { register char *ptr = dst; -- cgit v1.2.3