Browse Source

Fix usage_count in ldso/libdl.
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.

Joakim Tjernlund 20 years ago
parent
commit
9f47eaf322
3 changed files with 39 additions and 77 deletions
  1. 4 1
      ldso/ldso/ldso.c
  2. 1 1
      ldso/libdl/Makefile
  3. 34 75
      ldso/libdl/libdl.c

+ 4 - 1
ldso/ldso/ldso.c

@@ -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__)

+ 1 - 1
ldso/libdl/Makefile

@@ -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

+ 34 - 75
ldso/libdl/libdl.c

@@ -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);
 		}