Selaa lähdekoodia

Weed out duplicates before trying to load libraries.... Delayed
checking for duplicates and returning an alias if an existing lib
is already loaded is still correct for the dlopen case.

Eric Andersen 21 vuotta sitten
vanhempi
commit
9a927b3cbb
5 muutettua tiedostoa jossa 102 lisäystä ja 30 poistoa
  1. 1 0
      ldso/include/dl-elf.h
  2. 1 0
      ldso/include/ld_elf.h
  3. 44 15
      ldso/ldso/dl-elf.c
  4. 12 0
      ldso/ldso/ldso.c
  5. 44 15
      ldso/ldso/readelflib1.c

+ 1 - 0
ldso/include/dl-elf.h

@@ -68,6 +68,7 @@ extern struct elf_resolve * _dl_load_shared_library(int secure,
 	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
 	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 	struct dyn_elf **rpnt, char *libname);
 	struct dyn_elf **rpnt, char *libname);
+extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname);
 extern int _dl_linux_resolve(void);
 extern int _dl_linux_resolve(void);
 
 
 
 

+ 1 - 0
ldso/include/ld_elf.h

@@ -68,6 +68,7 @@ extern struct elf_resolve * _dl_load_shared_library(int secure,
 	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
 	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 	struct dyn_elf **rpnt, char *libname);
 	struct dyn_elf **rpnt, char *libname);
+extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname);
 extern int _dl_linux_resolve(void);
 extern int _dl_linux_resolve(void);
 
 
 
 

+ 44 - 15
ldso/ldso/dl-elf.c

@@ -166,29 +166,19 @@ search_for_named_library(char *name, int secure, const char *path_list,
 	return NULL;
 	return NULL;
 }
 }
 
 
-
-/*
- * Used to return error codes back to dlopen et. al.
- */
-
-unsigned long _dl_error_number;
-unsigned long _dl_internal_error_number;
-extern char *_dl_ldsopath;
-
-struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
-	struct elf_resolve *tpnt, char *full_libname)
+/* Check if the named library is already loaded... */
+struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname)
 {
 {
-	char *pnt, *pnt1;
+	const char *pnt, *pnt1;
 	struct elf_resolve *tpnt1;
 	struct elf_resolve *tpnt1;
-	char *libname, *libname2;
+	const char *libname, *libname2;
 
 
-	_dl_internal_error_number = 0;
 	pnt = libname = full_libname;
 	pnt = libname = full_libname;
 
 
 	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
 	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
 	   allow full_libname or any directory to be longer than 1024. */
 	   allow full_libname or any directory to be longer than 1024. */
 	if (_dl_strlen(full_libname) > 1024)
 	if (_dl_strlen(full_libname) > 1024)
-		goto goof;
+		return NULL;
 
 
 	/* Skip over any initial initial './' and '/' stuff to 
 	/* Skip over any initial initial './' and '/' stuff to 
 	 * get the short form libname with no path garbage */ 
 	 * get the short form libname with no path garbage */ 
@@ -215,8 +205,47 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 			return tpnt1;
 			return tpnt1;
 		}
 		}
 	}
 	}
+	return NULL;
+}
 	
 	
 
 
+
+/*
+ * Used to return error codes back to dlopen et. al.
+ */
+
+unsigned long _dl_error_number;
+unsigned long _dl_internal_error_number;
+extern char *_dl_ldsopath;
+
+struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+	struct elf_resolve *tpnt, char *full_libname)
+{
+	char *pnt, *pnt1;
+	struct elf_resolve *tpnt1;
+	char *libname;
+
+	_dl_internal_error_number = 0;
+	libname = full_libname;
+
+	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
+	   allow full_libname or any directory to be longer than 1024. */
+	if (_dl_strlen(full_libname) > 1024)
+		goto goof;
+
+	/* Skip over any initial initial './' and '/' stuff to 
+	 * get the short form libname with no path garbage */ 
+	pnt1 = _dl_strrchr(libname, '/');
+	if (pnt1) {
+		libname = pnt1 + 1;
+	}
+
+	/* Critical step!  Weed out duplicates early to avoid
+	 * function aliasing, which wastes memory, and causes
+	 * really bad things to happen with weaks and globals. */
+	if ((tpnt1=_dl_check_if_named_library_is_loaded(libname))!=NULL)
+		return tpnt1;
+
 #if defined (__SUPPORT_LD_DEBUG__)
 #if defined (__SUPPORT_LD_DEBUG__)
 	if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 	if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 #endif

+ 12 - 0
ldso/ldso/ldso.c

@@ -902,6 +902,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			*str2 = '\0';
 			*str2 = '\0';
 			if (!_dl_secure || _dl_strchr(str, '/') == NULL) 
 			if (!_dl_secure || _dl_strchr(str, '/') == NULL) 
 			{
 			{
+				if ((tpnt1 = _dl_check_if_named_library_is_loaded(str))) 
+				{
+					continue;
+				}
 				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
 				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
 				if (!tpnt1) {
 				if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
 #ifdef __LDSO_LDD_SUPPORT__
@@ -978,6 +982,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 						c = *cp;
 						c = *cp;
 						*cp = '\0';
 						*cp = '\0';
 
 
+						if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2))) 
+						{
+							continue;
+						}
 						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						if (!tpnt1) {
 						if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
 #ifdef __LDSO_LDD_SUPPORT__
@@ -1068,6 +1076,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 					tpnt = NULL;
 					tpnt = NULL;
 					continue;
 					continue;
 				}
 				}
+				if ((tpnt1 = _dl_check_if_named_library_is_loaded(lpntstr))) 
+				{
+					continue;
+				}
 				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
 				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
 				{
 				{
 #ifdef __LDSO_LDD_SUPPORT__
 #ifdef __LDSO_LDD_SUPPORT__

+ 44 - 15
ldso/ldso/readelflib1.c

@@ -166,29 +166,19 @@ search_for_named_library(char *name, int secure, const char *path_list,
 	return NULL;
 	return NULL;
 }
 }
 
 
-
-/*
- * Used to return error codes back to dlopen et. al.
- */
-
-unsigned long _dl_error_number;
-unsigned long _dl_internal_error_number;
-extern char *_dl_ldsopath;
-
-struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
-	struct elf_resolve *tpnt, char *full_libname)
+/* Check if the named library is already loaded... */
+struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname)
 {
 {
-	char *pnt, *pnt1;
+	const char *pnt, *pnt1;
 	struct elf_resolve *tpnt1;
 	struct elf_resolve *tpnt1;
-	char *libname, *libname2;
+	const char *libname, *libname2;
 
 
-	_dl_internal_error_number = 0;
 	pnt = libname = full_libname;
 	pnt = libname = full_libname;
 
 
 	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
 	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
 	   allow full_libname or any directory to be longer than 1024. */
 	   allow full_libname or any directory to be longer than 1024. */
 	if (_dl_strlen(full_libname) > 1024)
 	if (_dl_strlen(full_libname) > 1024)
-		goto goof;
+		return NULL;
 
 
 	/* Skip over any initial initial './' and '/' stuff to 
 	/* Skip over any initial initial './' and '/' stuff to 
 	 * get the short form libname with no path garbage */ 
 	 * get the short form libname with no path garbage */ 
@@ -215,8 +205,47 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 			return tpnt1;
 			return tpnt1;
 		}
 		}
 	}
 	}
+	return NULL;
+}
 	
 	
 
 
+
+/*
+ * Used to return error codes back to dlopen et. al.
+ */
+
+unsigned long _dl_error_number;
+unsigned long _dl_internal_error_number;
+extern char *_dl_ldsopath;
+
+struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+	struct elf_resolve *tpnt, char *full_libname)
+{
+	char *pnt, *pnt1;
+	struct elf_resolve *tpnt1;
+	char *libname;
+
+	_dl_internal_error_number = 0;
+	libname = full_libname;
+
+	/* quick hack to ensure mylibname buffer doesn't overflow.  don't 
+	   allow full_libname or any directory to be longer than 1024. */
+	if (_dl_strlen(full_libname) > 1024)
+		goto goof;
+
+	/* Skip over any initial initial './' and '/' stuff to 
+	 * get the short form libname with no path garbage */ 
+	pnt1 = _dl_strrchr(libname, '/');
+	if (pnt1) {
+		libname = pnt1 + 1;
+	}
+
+	/* Critical step!  Weed out duplicates early to avoid
+	 * function aliasing, which wastes memory, and causes
+	 * really bad things to happen with weaks and globals. */
+	if ((tpnt1=_dl_check_if_named_library_is_loaded(libname))!=NULL)
+		return tpnt1;
+
 #if defined (__SUPPORT_LD_DEBUG__)
 #if defined (__SUPPORT_LD_DEBUG__)
 	if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 	if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 #endif