summaryrefslogtreecommitdiffstats
path: root/ldso/libdl
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-10-09 06:05:35 +0000
committerEric Andersen <andersen@codepoet.org>2003-10-09 06:05:35 +0000
commitcca32e60f4052751c719687c5a1639314c7b1430 (patch)
tree4a9aaceb5caecae3ae3826554e4627000b3cdb37 /ldso/libdl
parentabd02d7387069439373d40c2f9afba93c76df650 (diff)
downloaduClibc-alpine-cca32e60f4052751c719687c5a1639314c7b1430.tar.bz2
uClibc-alpine-cca32e60f4052751c719687c5a1639314c7b1430.tar.xz
When someone would dlopen a shared lib that was already opened,
we would try to re-fixup the lib's relocations with rather horrible results. So fix that by checking the the dlopened lib has already had its init functions called, which will never be the case for newly loaded libs, and skip the rest in that case. also apply a few minor fixups
Diffstat (limited to 'ldso/libdl')
-rw-r--r--ldso/libdl/dlib.c26
-rw-r--r--ldso/libdl/libdl.c26
2 files changed, 28 insertions, 24 deletions
diff --git a/ldso/libdl/dlib.c b/ldso/libdl/dlib.c
index dec41848c..c54104ffe 100644
--- a/ldso/libdl/dlib.c
+++ b/ldso/libdl/dlib.c
@@ -181,12 +181,18 @@ void *_dlopen(const char *libname, int flag)
if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
#endif
- if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname))) {
+ tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname);
+ if (tpnt == NULL) {
_dl_unmap_cache();
return NULL;
}
- //tpnt->libtype = loaded_file;
+ if (tpnt->init_flag & INIT_FUNCS_CALLED) {
+ /* If the init and fini stuff has already been run, that means
+ * someone called dlopen on a library we already have opened, so
+ * we don't need to fix thing up any further... */
+ return tpnt;
+ }
dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
_dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
@@ -203,6 +209,7 @@ void *_dlopen(const char *libname, int flag)
if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
#endif
+
for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
{
Elf32_Dyn *dpnt;
@@ -220,22 +227,17 @@ void *_dlopen(const char *libname, int flag)
_dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
lpntstr, tcurr->libname);
#endif
-#if 0
- if ((tpnt1 = _dl_check_if_named_library_is_loaded(name)))
- {
- /* If the needed library is already loaded, then we
- * need to override all globals and weaks in the current
- * chain... Or something. */
- continue;
- }
-#endif
if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) {
goto oops;
}
+
+#if 1
+//FIXME: Enabling this is _so_ wrong....
/* We need global symbol resolution for everything
* in the dependent chain */
dyn_chain->flags |= RTLD_GLOBAL;
+#endif
rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
_dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
@@ -269,7 +271,7 @@ void *_dlopen(const char *libname, int flag)
* Now we go through and look for REL and RELA records that indicate fixups
* to the GOT tables. We need to do this in reverse order so that COPY
* directives work correctly */
- if (_dl_fixup(dyn_chain->dyn, (dyn_chain->flags & RTLD_LAZY)))
+ if (_dl_fixup(dyn_chain->dyn, dyn_chain->flags))
goto oops;
#ifdef __SUPPORT_LD_DEBUG__
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index dec41848c..c54104ffe 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -181,12 +181,18 @@ void *_dlopen(const char *libname, int flag)
if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
#endif
- if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname))) {
+ tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname);
+ if (tpnt == NULL) {
_dl_unmap_cache();
return NULL;
}
- //tpnt->libtype = loaded_file;
+ if (tpnt->init_flag & INIT_FUNCS_CALLED) {
+ /* If the init and fini stuff has already been run, that means
+ * someone called dlopen on a library we already have opened, so
+ * we don't need to fix thing up any further... */
+ return tpnt;
+ }
dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
_dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
@@ -203,6 +209,7 @@ void *_dlopen(const char *libname, int flag)
if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
#endif
+
for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
{
Elf32_Dyn *dpnt;
@@ -220,22 +227,17 @@ void *_dlopen(const char *libname, int flag)
_dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
lpntstr, tcurr->libname);
#endif
-#if 0
- if ((tpnt1 = _dl_check_if_named_library_is_loaded(name)))
- {
- /* If the needed library is already loaded, then we
- * need to override all globals and weaks in the current
- * chain... Or something. */
- continue;
- }
-#endif
if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) {
goto oops;
}
+
+#if 1
+//FIXME: Enabling this is _so_ wrong....
/* We need global symbol resolution for everything
* in the dependent chain */
dyn_chain->flags |= RTLD_GLOBAL;
+#endif
rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
_dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
@@ -269,7 +271,7 @@ void *_dlopen(const char *libname, int flag)
* Now we go through and look for REL and RELA records that indicate fixups
* to the GOT tables. We need to do this in reverse order so that COPY
* directives work correctly */
- if (_dl_fixup(dyn_chain->dyn, (dyn_chain->flags & RTLD_LAZY)))
+ if (_dl_fixup(dyn_chain->dyn, dyn_chain->flags))
goto oops;
#ifdef __SUPPORT_LD_DEBUG__