[uClibc] [RFC] don't use atexit() for FINI processing in ldso.

Joakim Tjernlund joakim.tjernlund at lumentis.se
Fri Mar 18 11:59:10 UTC 2005


As discussed on IRC yesterday, here is a patch(PPC only) to remove
atexit() from ldso. This should make Valgind happier since there won't
be any malloc()s that Valgind won't see.

The proposed solution changes ABI and all apps needs to be relinked.

TODO:
Fix remaining archs and possibly clean up the i/f between
ldso/crt0 and __uClibc_main since this patch already breaks ABI.
Remove some dead code in ldso.

Comments?

Index: ldso/ldso/powerpc/dl-startup.h
===================================================================
--- ldso/ldso/powerpc/dl-startup.h	(revision 10036)
+++ ldso/ldso/powerpc/dl-startup.h	(working copy)
@@ -15,6 +15,9 @@
     "	stw	4,0(1)\n" /* Clear Stack frame */
     "	bl	_dl_start at local\n" /* Perform relocation */
     "	addi	1,1,16\n" /* Restore SP */
+    "	bl	_GLOBAL_OFFSET_TABLE_-4 at local\n" /*  Put our GOT pointer in r31, */
+    "	mflr	31\n"
+    "	lwz	7,_dl_fini at got(31)\n"
     "	mtctr	3\n" /* Load applications entry point */
     "	bctr\n" /* Jump to entry point */
     "	.size	_start,.-_start\n"
Index: ldso/ldso/ldso.c
===================================================================
--- ldso/ldso/ldso.c	(revision 10036)
+++ ldso/ldso/ldso.c	(working copy)
@@ -75,6 +75,9 @@
 static unsigned char *_dl_malloc_addr = 0;	/* Lets _dl_malloc use the already allocated memory page */
 static unsigned char *_dl_mmap_zero   = 0;	/* Also used by _dl_malloc */
 
+static struct elf_resolve **init_fini_list;
+static int nlist; /* # items in init_fini_list */
+
 #if defined (__SUPPORT_LD_DEBUG__)
 static void debug_fini (int status, void *arg)
 {
@@ -92,8 +95,7 @@
 	ElfW(Phdr) *ppnt;
 	Elf32_Dyn *dpnt;
 	char *lpntstr;
-	int i, nlist, goof = 0, unlazy = 0, trace_loaded_objects = 0;
-	struct elf_resolve **init_fini_list;
+	int i, goof = 0, unlazy = 0, trace_loaded_objects = 0;
 	struct dyn_elf *rpnt;
 	struct elf_resolve *tcurr;
 	struct elf_resolve *tpnt1;
@@ -613,12 +615,14 @@
 	_dl_unmap_cache();
 
 	--nlist; /* Exclude the application. */
-
+#if 0
 	/* As long as atexit() is used to run the FINI functions, we can use
 	 * alloca here. The use of atexit() should go away at some time as that
 	 * will make Valgring happy.
 	 */
 	init_fini_list = alloca(nlist * sizeof(struct elf_resolve *));
+#endif
+	init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));
 	i = 0;
 	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
 		init_fini_list[i++] = tcurr;
@@ -818,6 +822,7 @@
 
 			(*dl_elf_func) ();
 		}
+#if 0
 		tpnt->init_flag |= FINI_FUNCS_CALLED;
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 			void (*dl_elf_func) (void);
@@ -836,6 +841,7 @@
 				_dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
 		}
 #endif
+#endif
 	}
 
 	/* Notify the debugger that all objects are now mapped in.  */
@@ -846,6 +852,31 @@
 	 _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
 }
 
+static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
+{
+	int i;
+	struct elf_resolve * tpnt;
+
+	for (i = 0; i < nlist; ++i) {
+		tpnt = init_fini_list[i];
+		if (tpnt->init_flag & FINI_FUNCS_CALLED)
+			continue;
+		tpnt->init_flag |= FINI_FUNCS_CALLED;
+		if (tpnt->dynamic_info[DT_FINI]) {
+			void (*dl_elf_func) (void);
+
+			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+#if defined (__SUPPORT_LD_DEBUG__)
+			if(_dl_debug)
+				_dl_dprintf(_dl_debug_file,
+					    "\ncalling FINI: %s\n\n",
+					    tpnt->libname);
+#endif
+			(*dl_elf_func) ();
+		}
+	}
+}
+
 char *_dl_getenv(const char *symbol, char **envp)
 {
 	char *pnt;
Index: libc/stdlib/atexit.c
===================================================================
--- libc/stdlib/atexit.c	(revision 9939)
+++ libc/stdlib/atexit.c	(working copy)
@@ -222,6 +222,7 @@
 extern void (*__app_fini)(void);
 #endif
 
+extern void (*__rtld_fini)(void);
 /*
  * Normal program termination
  */
@@ -238,6 +239,8 @@
 	if (__app_fini != NULL)
 		(__app_fini)();
 #endif
+	if (__rtld_fini != NULL)
+		(__rtld_fini)();
 
     /* If we are using stdio, try to shut it down.  At the very least,
 	 * this will attempt to commit all buffered writes.  It may also
Index: libc/sysdeps/linux/powerpc/crt0.S
===================================================================
--- libc/sysdeps/linux/powerpc/crt0.S	(revision 10041)
+++ libc/sysdeps/linux/powerpc/crt0.S	(working copy)
@@ -70,6 +70,7 @@
 	addi	r5,r5,1
 	rlwinm	r5,r5,2,0,29
 	add	r5,r5,r4
+	mr	r8,r7 /* Pass _dl_fini from ldso */
 	/* Ok, now run uClibc's main() -- shouldn't return */
 #if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__
 # ifdef L_Scrt1
Index: libc/misc/internals/__uClibc_main.c
===================================================================
--- libc/misc/internals/__uClibc_main.c	(revision 9939)
+++ libc/misc/internals/__uClibc_main.c	(working copy)
@@ -155,16 +155,18 @@
 }
 
 #ifdef __UCLIBC_CTOR_DTOR__
-void (*__app_fini)(void) = NULL;
+void attribute_hidden (*__app_fini)(void) = NULL;
 #endif
 
+void attribute_hidden (*__rtld_fini)(void) = NULL;
+
 /* __uClibc_start_main is the new main stub for uClibc. This function is
  * called from crt0 (version 0.9.16 or newer), after ALL shared libraries
  * are initialized, just before we call the application's main function.
  */
 void __attribute__ ((__noreturn__))
 __uClibc_start_main(int argc, char **argv, char **envp,
-	void (*app_init)(void), void (*app_fini)(void))
+	void (*app_init)(void), void (*app_fini)(void), void (*rtld_fini)(void))
 {
 #ifdef __ARCH_HAS_MMU__
     unsigned long *aux_dat;
@@ -176,6 +178,8 @@
      * __uClibc_init() regardless, to be sure the right thing happens. */
     __uClibc_init();
 
+    __rtld_fini = rtld_fini;
+
     /* If we are dynamically linked, then ldso already did this for us. */
     if (__environ==NULL) {
 	/* Statically linked. */
@@ -260,6 +264,6 @@
 void __attribute__ ((__noreturn__))
 __uClibc_main(int argc, char **argv, char ** envp)
 {
-    __uClibc_start_main(argc, argv, envp, NULL, NULL);
+    __uClibc_start_main(argc, argv, envp, NULL, NULL, NULL);
 }
 





More information about the uClibc mailing list