Browse Source

Fix the library searching routine so it is way simpler, and so
it matches the routine in ldd.c

Eric Andersen 23 years ago
parent
commit
51ff0f67c7
4 changed files with 170 additions and 266 deletions
  1. 69 132
      ldso/ldso/dl-elf.c
  2. 16 1
      ldso/ldso/ld_string.h
  3. 69 132
      ldso/ldso/readelflib1.c
  4. 16 1
      ldso/ldso/string.h

+ 69 - 132
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 <prefix>/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 <prefix>/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 <devel-dir>/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 <builddir>/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 */

+ 16 - 1
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;

+ 69 - 132
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 <prefix>/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 <prefix>/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 <devel-dir>/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 <builddir>/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 */

+ 16 - 1
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;