Browse Source

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

Eric Andersen 23 năm trước cách đây
mục cha
commit
51ff0f67c7
4 tập tin đã thay đổi với 170 bổ sung266 xóa
  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;