svn commit: trunk/uClibc: ldso/ldso ldso/libdl libc/misc/internals etc...

vapier at uclibc.org vapier at uclibc.org
Tue Feb 14 01:02:29 UTC 2006


Author: vapier
Date: 2006-02-13 17:02:26 -0800 (Mon, 13 Feb 2006)
New Revision: 13961

Log:
after much deliberation, may i present Joseph S. Myers patch to add support for .init and .fini array processing
for the gory details, see the mailing list:
http://www.uclibc.org/lists/uclibc/2006-January/014079.html
http://www.uclibc.org/lists/uclibc/2006-February/014285.html


Modified:
   trunk/uClibc/ldso/ldso/ldso.c
   trunk/uClibc/ldso/libdl/libdl.c
   trunk/uClibc/libc/misc/internals/__uClibc_main.c
   trunk/uClibc/libc/stdlib/_atexit.c


Changeset:
Modified: trunk/uClibc/ldso/ldso/ldso.c
===================================================================
--- trunk/uClibc/ldso/ldso/ldso.c	2006-02-14 00:17:21 UTC (rev 13960)
+++ trunk/uClibc/ldso/ldso/ldso.c	2006-02-14 01:02:26 UTC (rev 13961)
@@ -97,6 +97,53 @@
 #endif
 #endif
 
+static void _dl_run_array_forward(unsigned long array, unsigned long size,
+				  ElfW(Addr) loadaddr)
+{
+	if (array != 0) {
+		unsigned int j;
+		unsigned int jm;
+		ElfW(Addr) *addrs;
+		jm = size / sizeof (ElfW(Addr));
+		addrs = (ElfW(Addr) *) (array + loadaddr);
+		for (j = 0; j < jm; ++j) {
+			void (*dl_elf_func) (void);
+			dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
+			(*dl_elf_func) ();
+		}
+	}
+}
+
+void _dl_run_init_array(struct elf_resolve *tpnt)
+{
+	_dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY],
+			      tpnt->dynamic_info[DT_INIT_ARRAYSZ],
+			      tpnt->loadaddr);
+}
+
+void _dl_app_init_array(void)
+{
+	_dl_run_init_array(_dl_loaded_modules);
+}
+
+void _dl_run_fini_array(struct elf_resolve *tpnt)
+{
+	if (tpnt->dynamic_info[DT_FINI_ARRAY]) {
+		ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]);
+		unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr)));
+		while (i-- > 0) {
+			void (*dl_elf_func) (void);
+			dl_elf_func = (void (*)(void)) (intptr_t) array[i];
+			(*dl_elf_func) ();
+		}
+	}
+}
+
+void _dl_app_fini_array(void)
+{
+	_dl_run_fini_array(_dl_loaded_modules);
+}
+
 static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
 {
 	int i;
@@ -107,6 +154,7 @@
 		if (tpnt->init_flag & FINI_FUNCS_CALLED)
 			continue;
 		tpnt->init_flag |= FINI_FUNCS_CALLED;
+		_dl_run_fini_array(tpnt);
 		if (tpnt->dynamic_info[DT_FINI]) {
 			void (*dl_elf_func) (void);
 
@@ -769,6 +817,14 @@
 	/* Notify the debugger we have added some objects. */
 	_dl_debug_addr->r_state = RT_ADD;
 	_dl_debug_state();
+
+	/* Run pre-initialization functions for the executable.  */
+	_dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY],
+			      _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ],
+			      _dl_loaded_modules->loadaddr);
+
+	/* Run initialization functions for loaded objects.  For the
+	   main executable, they will be run from __uClibc_main.  */
 	for (i = nlist; i; --i) {
 		tpnt = init_fini_list[i-1];
 		tpnt->init_fini = NULL; /* Clear, since alloca was used */
@@ -785,6 +841,8 @@
 
 			(*dl_elf_func) ();
 		}
+
+		_dl_run_init_array(tpnt);
 	}
 
 	/* Find the real malloc function and make ldso functions use that from now on */

Modified: trunk/uClibc/ldso/libdl/libdl.c
===================================================================
--- trunk/uClibc/ldso/libdl/libdl.c	2006-02-14 00:17:21 UTC (rev 13960)
+++ trunk/uClibc/ldso/libdl/libdl.c	2006-02-14 01:02:26 UTC (rev 13961)
@@ -51,6 +51,8 @@
 extern struct r_debug *_dl_debug_addr;
 extern unsigned long _dl_error_number;
 extern void *(*_dl_malloc_function)(size_t);
+extern void _dl_run_init_array(struct elf_resolve *);
+extern void _dl_run_fini_array(struct elf_resolve *);
 #ifdef __LDSO_CACHE_SUPPORT__
 int _dl_map_cache(void);
 int _dl_unmap_cache(void);
@@ -383,6 +385,8 @@
 				(*dl_elf_func) ();
 			}
 		}
+
+		_dl_run_init_array(tpnt);
 	}
 #endif /* SHARED */
 
@@ -498,13 +502,21 @@
 	for (j = 0; j < handle->init_fini.nlist; ++j) {
 		tpnt = handle->init_fini.init_fini[j];
 		if (--tpnt->usage_count == 0) {
-			if (tpnt->dynamic_info[DT_FINI] && need_fini &&
+			if ((tpnt->dynamic_info[DT_FINI]
+			     || tpnt->dynamic_info[DT_FINI_ARRAY])
+			    && need_fini &&
 			    !(tpnt->init_flag & FINI_FUNCS_CALLED)) {
 				tpnt->init_flag |= FINI_FUNCS_CALLED;
-				dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
-				_dl_if_debug_print("running dtors for library %s at '%p'\n",
-						tpnt->libname, dl_elf_fini);
-				(*dl_elf_fini) ();
+#ifdef SHARED
+				_dl_run_fini_array(tpnt);
+#endif
+
+				if (tpnt->dynamic_info[DT_FINI]) {
+					dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+					_dl_if_debug_print("running dtors for library %s at '%p'\n",
+							tpnt->libname, dl_elf_fini);
+					(*dl_elf_fini) ();
+				}
 			}
 
 			_dl_if_debug_print("unmapping: %s\n", tpnt->libname);

Modified: trunk/uClibc/libc/misc/internals/__uClibc_main.c
===================================================================
--- trunk/uClibc/libc/misc/internals/__uClibc_main.c	2006-02-14 00:17:21 UTC (rev 13960)
+++ trunk/uClibc/libc/misc/internals/__uClibc_main.c	2006-02-14 01:02:26 UTC (rev 13961)
@@ -84,6 +84,20 @@
 extern void weak_function __pthread_initialize_minimal(void);
 #endif
 
+#ifdef __UCLIBC_CTOR_DTOR__
+extern void _dl_app_init_array(void);
+extern void _dl_app_fini_array(void);
+#ifndef SHARED
+/* These magic symbols are provided by the linker.  */
+extern void (*__preinit_array_start []) (void) attribute_hidden;
+extern void (*__preinit_array_end []) (void) attribute_hidden;
+extern void (*__init_array_start []) (void) attribute_hidden;
+extern void (*__init_array_end []) (void) attribute_hidden;
+extern void (*__fini_array_start []) (void) attribute_hidden;
+extern void (*__fini_array_end []) (void) attribute_hidden;
+#endif
+#endif
+
 attribute_hidden const char *__uclibc_progname = NULL;
 #ifdef __UCLIBC_HAS___PROGNAME__
 strong_alias (__uclibc_progname, __progname)
@@ -228,6 +242,26 @@
 
 void attribute_hidden (*__rtld_fini)(void) = NULL;
 
+extern void __uClibc_fini(void);
+libc_hidden_proto(__uClibc_fini)
+void __uClibc_fini(void)
+{
+#ifdef __UCLIBC_CTOR_DTOR__
+#ifdef SHARED
+    _dl_app_fini_array();
+#else
+    size_t i = __fini_array_end - __fini_array_start;
+    while (i-- > 0)
+	(*__fini_array_start [i]) ();
+#endif
+    if (__app_fini != NULL)
+	(__app_fini)();
+#endif
+    if (__rtld_fini != NULL)
+	(__rtld_fini)();
+}
+libc_hidden_def(__uClibc_fini)
+
 /* __uClibc_main is the new main stub for uClibc. This function is
  * called from crt1 (version 0.9.28 or newer), after ALL shared libraries
  * are initialized, just before we call the application's main function.
@@ -313,11 +347,32 @@
     /* Arrange for the application's dtors to run before we exit.  */
     __app_fini = app_fini;
 
+#ifndef SHARED
+    /* For dynamically linked executables the preinit array is executed by
+       the dynamic linker (before initializing any shared object).
+       For static executables, preinit happens rights before init.  */
+    {
+	const size_t size = __preinit_array_end - __preinit_array_start;
+	size_t i;
+	for (i = 0; i < size; i++)
+	    (*__preinit_array_start [i]) ();
+    }
+#endif
     /* Run all the application's ctors now.  */
     if (app_init!=NULL) {
 	app_init();
     }
+#ifdef SHARED
+    _dl_app_init_array();
+#else
+    {
+	const size_t size = __init_array_end - __init_array_start;
+	size_t i;
+	for (i = 0; i < size; i++)
+	    (*__init_array_start [i]) ();
+    }
 #endif
+#endif
 
     /* Note: It is possible that any initialization done above could
      * have resulted in errno being set nonzero, so set it to 0 before

Modified: trunk/uClibc/libc/stdlib/_atexit.c
===================================================================
--- trunk/uClibc/libc/stdlib/_atexit.c	2006-02-14 00:17:21 UTC (rev 13960)
+++ trunk/uClibc/libc/stdlib/_atexit.c	2006-02-14 01:02:26 UTC (rev 13961)
@@ -318,12 +318,9 @@
 libc_hidden_data_def(mylock)
 #endif
 
-#ifdef __UCLIBC_CTOR_DTOR__
-extern void (*__app_fini)(void);
-#endif
+extern void __uClibc_fini(void);
+libc_hidden_proto(__uClibc_fini)
 
-extern void (*__rtld_fini)(void);
-
 /*
  * Normal program termination
  */
@@ -336,12 +333,7 @@
 	}
 	UNLOCK;
 
-#ifdef __UCLIBC_CTOR_DTOR__
-	if (__app_fini != NULL)
-		(__app_fini)();
-#endif
-	if (__rtld_fini != NULL)
-		(__rtld_fini)();
+	__uClibc_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




More information about the uClibc-cvs mailing list