Browse Source

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 years ago
parent
commit
9a927b3cbb
5 changed files with 102 additions and 30 deletions
  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);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 	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);
 
 

+ 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);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
 	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);
 
 

+ 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;
 }
 
-
-/*
- * 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;
-	char *libname, *libname2;
+	const char *libname, *libname2;
 
-	_dl_internal_error_number = 0;
 	pnt = 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;
+		return NULL;
 
 	/* Skip over any initial initial './' and '/' stuff to 
 	 * 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 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(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #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';
 			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);
 				if (!tpnt1) {
 #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;
 						*cp = '\0';
 
+						if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2))) 
+						{
+							continue;
+						}
 						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						if (!tpnt1) {
 #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;
 					continue;
 				}
+				if ((tpnt1 = _dl_check_if_named_library_is_loaded(lpntstr))) 
+				{
+					continue;
+				}
 				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
 				{
 #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;
 }
 
-
-/*
- * 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;
-	char *libname, *libname2;
+	const char *libname, *libname2;
 
-	_dl_internal_error_number = 0;
 	pnt = 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;
+		return NULL;
 
 	/* Skip over any initial initial './' and '/' stuff to 
 	 * 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 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(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif