summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/include/dl-elf.h1
-rw-r--r--ldso/include/ld_elf.h1
-rw-r--r--ldso/ldso/dl-elf.c59
-rw-r--r--ldso/ldso/ldso.c12
-rw-r--r--ldso/ldso/readelflib1.c59
5 files changed, 102 insertions, 30 deletions
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index 95de118f5..992a608b1 100644
--- a/ldso/include/dl-elf.h
+++ b/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);
diff --git a/ldso/include/ld_elf.h b/ldso/include/ld_elf.h
index 95de118f5..992a608b1 100644
--- a/ldso/include/ld_elf.h
+++ b/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);
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 3df8b1461..2f70621d1 100644
--- a/ldso/ldso/dl-elf.c
+++ b/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
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 2f8e611ba..b6f236d0b 100644
--- a/ldso/ldso/ldso.c
+++ b/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__
diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c
index 3df8b1461..2f70621d1 100644
--- a/ldso/ldso/readelflib1.c
+++ b/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