OSDN Git Service

Fix usage_count in ldso/libdl.
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>
Fri, 13 Aug 2004 13:56:25 +0000 (13:56 -0000)
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>
Fri, 13 Aug 2004 13:56:25 +0000 (13:56 -0000)
Don't' use atexit in libdl.
Make destrutor in libdl actually run and to dlclose all
dlopened libs.
Remove dlclosed libs from the _dl_symbol_tables list.

ldso/ldso/ldso.c
ldso/libdl/Makefile
ldso/libdl/libdl.c

index 70e8019..4256189 100644 (file)
@@ -183,7 +183,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
                                continue;
 #endif
                        /* OK, we have what we need - slip this one into the list. */
-                       app_tpnt = _dl_add_elf_hash_table("", (char *)app_tpnt->loadaddr,
+                       app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr,
                                        app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
                        _dl_loaded_modules->libtype = elf_executable;
                        _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
@@ -364,6 +364,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
                        {
                                if ((tpnt1 = _dl_check_if_named_library_is_loaded(str, trace_loaded_objects)))
                                {
+                                       tpnt1->usage_count++;
                                        continue;
                                }
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -448,6 +449,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
 
                                                if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2, trace_loaded_objects)))
                                                {
+                                                       tpnt1->usage_count++;
                                                        continue;
                                                }
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -503,6 +505,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
 
                                if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects)))
                                {
+                                       tpnt1->usage_count++;
                                        continue;
                                }
 #if defined (__SUPPORT_LD_DEBUG__)
index 9e2fb09..f10510f 100644 (file)
@@ -73,7 +73,7 @@ $(OBJ): Makefile
 
 shared:
        $(LD) $(LDFLAGS) -soname=$(LIBDL_SHARED).$(MAJOR_VERSION) \
-               -o $(LIBDL_SHARED_FULLNAME) --whole-archive $(LIBDL_PIC) \
+               -o $(LIBDL_SHARED_FULLNAME) -fini dl_cleanup --whole-archive $(LIBDL_PIC) \
                --no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
                -L$(TOPDIR)/lib -lc $(LDADD_LIBFLOAT) $(LIBGCC);
        $(INSTALL) -d $(TOPDIR)lib
index 03b7834..fd72509 100644 (file)
@@ -117,15 +117,12 @@ static const char *dl_error_names[] = {
        "Unable to resolve symbol"
 };
 
-static void __attribute__ ((destructor)) dl_cleanup(void)
+void __attribute__ ((destructor)) dl_cleanup(void)
 {
        struct dyn_elf *d;
-
-       for (d = _dl_handles; d; d = d->next_handle)
-               if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) {
-                       (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) ();
-                       d->dyn->dynamic_info[DT_FINI] = 0;
-               }
+       for (d = _dl_handles; d; d = d->next_handle) {
+               do_dlclose(d, 1);
+       }
 }
 
 void *dlopen(const char *libname, int flag)
@@ -227,6 +224,8 @@ void *dlopen(const char *libname, int flag)
                                        if (!tpnt1)
                                                goto oops;
                                        dyn_ptr->dyn = tpnt1;
+                               } else {
+                                       tpnt1->usage_count++;
                                }
                        }
                }
@@ -303,17 +302,6 @@ void *dlopen(const char *libname, int flag)
                                (*dl_elf_func) ();
                        }
                }
-               if (tpnt->dynamic_info[DT_FINI]) {
-                       void (*dl_elf_func) (void);
-                       dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
-                       if (dl_elf_func && *dl_elf_func != NULL) {
-#ifdef __SUPPORT_LD_DEBUG__
-                               if(_dl_debug)
-                                       fprintf(stderr, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
-#endif
-                               atexit(dl_elf_func);
-                       }
-               }
        }
 #endif
        return (void *) dyn_chain;
@@ -382,7 +370,6 @@ void *dlsym(void *vhandle, const char *name)
 static int do_dlclose(void *vhandle, int need_fini)
 {
        struct dyn_elf *rpnt, *rpnt1;
-       struct dyn_elf *spnt, *spnt1;
        ElfW(Phdr) *ppnt;
        struct elf_resolve *tpnt;
        int (*dl_elf_fini) (void);
@@ -394,9 +381,8 @@ static int do_dlclose(void *vhandle, int need_fini)
        handle = (struct dyn_elf *) vhandle;
        rpnt1 = NULL;
        for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
-               if (rpnt == handle) {
+               if (rpnt == handle)
                        break;
-               }
                rpnt1 = rpnt;
        }
 
@@ -404,74 +390,31 @@ static int do_dlclose(void *vhandle, int need_fini)
                _dl_error_number = LD_BAD_HANDLE;
                return 1;
        }
-
-       /* OK, this is a valid handle - now close out the file.
-        * We check if we need to call fini () on the handle. */
-       spnt = need_fini ? handle : handle->next;
-       for (; spnt; spnt = spnt1) {
-               spnt1 = spnt->next;
-
-               /* We appended the module list to the end - when we get back here,
-                  quit. The access counts were not adjusted to account for being here. */
-               if (spnt == _dl_symbol_tables)
-                       break;
-               if (spnt->dyn->usage_count == 1
-                               && spnt->dyn->libtype == loaded_file) {
-                       tpnt = spnt->dyn;
-                       /* Apparently crt1 for the application is responsible for handling this.
-                        * We only need to run the init/fini for shared libraries
-                        */
-
-                       if (tpnt->dynamic_info[DT_FINI]) {
-                               dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
-                                               tpnt->dynamic_info[DT_FINI]);
-                               (*dl_elf_fini) ();
-                       }
-               }
-       }
        if (rpnt1)
                rpnt1->next_handle = rpnt->next_handle;
        else
                _dl_handles = rpnt->next_handle;
-
        /* OK, this is a valid handle - now close out the file */
-       for (rpnt = handle; rpnt; rpnt = rpnt1) {
-               rpnt1 = rpnt->next;
-
-               /* We appended the module list to the end - when we get back here,
-                  quit. The access counts were not adjusted to account for being here. */
-               if (rpnt == _dl_symbol_tables)
-                       break;
-
-               rpnt->dyn->usage_count--;
-               if (rpnt->dyn->usage_count == 0
-                               && rpnt->dyn->libtype == loaded_file) {
-                       tpnt = rpnt->dyn;
-                       /* Apparently crt1 for the application is responsible for handling this.
-                        * We only need to run the init/fini for shared libraries
-                        */
-#if 0
-
-                       /* We have to do this above, before we start closing objects.
-                        * Otherwise when the needed symbols for _fini handling are
-                        * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
-                       if (tpnt->dynamic_info[DT_FINI]) {
+       for (rpnt = handle; rpnt; rpnt = rpnt->next) {
+               tpnt = rpnt->dyn;
+               if (--tpnt->usage_count == 0) {
+                       if (need_fini && tpnt->dynamic_info[DT_FINI]) {
                                dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
                                (*dl_elf_fini) ();
                        }
-#endif
+
                        end = 0;
-                       for (i = 0, ppnt = rpnt->dyn->ppnt;
-                                       i < rpnt->dyn->n_phent; ppnt++, i++) {
+                       for (i = 0, ppnt = tpnt->ppnt;
+                                       i < tpnt->n_phent; ppnt++, i++) {
                                if (ppnt->p_type != PT_LOAD)
                                        continue;
                                if (end < ppnt->p_vaddr + ppnt->p_memsz)
                                        end = ppnt->p_vaddr + ppnt->p_memsz;
                        }
-                       _dl_munmap((void*)rpnt->dyn->loadaddr, end);
-                       /* Next, remove rpnt->dyn from the loaded_module list */
-                       if (_dl_loaded_modules == rpnt->dyn) {
-                               _dl_loaded_modules = rpnt->dyn->next;
+                       _dl_munmap((void*)tpnt->loadaddr, end);
+                       /* Next, remove tpnt from the loaded_module list */
+                       if (_dl_loaded_modules == tpnt) {
+                               _dl_loaded_modules = tpnt->next;
                                if (_dl_loaded_modules)
                                        _dl_loaded_modules->prev = 0;
                        } else
@@ -482,6 +425,22 @@ static int do_dlclose(void *vhandle, int need_fini)
                                                        tpnt->next->prev = tpnt;
                                                break;
                                        }
+
+                       /* Next, remove tpnt from the global symbol table list */
+                       if (_dl_symbol_tables->dyn == rpnt->dyn) {
+                               _dl_symbol_tables = rpnt->next;
+                               if (_dl_symbol_tables)
+                                       _dl_symbol_tables->prev = 0;
+                       } else
+                               for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) {
+                                       if (rpnt1->next->dyn == rpnt->dyn) {
+                                               free(rpnt1->next);
+                                               rpnt1->next = rpnt1->next->next;
+                                               if (rpnt1->next)
+                                                       rpnt1->next->prev = rpnt1;
+                                               break;
+                                       }
+                               }
                        free(rpnt->dyn->libname);
                        free(rpnt->dyn);
                }