[patch] init_array/fini_array support

Joseph S. Myers joseph at codesourcery.com
Sun Jan 29 20:23:54 UTC 2006


On Tue, 24 Jan 2006, Joakim Tjernlund wrote:

> > What do you think of the size increase? Couldn't we move at 
> > least some of it to ld.so? Is there some other reason to have 
> > them local in the binary?
> 
> That's an interesting idea, but not so easy I think. One would have to move
> the apps _init/_fini processing to ld.so and remove them from crt1 or some combination
> of both to support static linking.

Indeed, static binaries need __libc_csu_fini so avoiding it altogether for 
dynamic binaries (instead calling destructors from ld.so) would mean 
different copies of crt1 for static and dynamic linking.

Here is a refreshed version of my patch relative to today's trunk.  There 
are no substantive changes to the approach but it's updated for the 
various changes to crt1 files since my last patch version.

Index: ldso/ldso/ldso.c
===================================================================
--- ldso/ldso/ldso.c	(revision 13657)
+++ ldso/ldso/ldso.c	(working copy)
@@ -107,6 +107,15 @@
 		if (tpnt->init_flag & FINI_FUNCS_CALLED)
 			continue;
 		tpnt->init_flag |= FINI_FUNCS_CALLED;
+		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) ();
+			}
+		}
 		if (tpnt->dynamic_info[DT_FINI]) {
 			void (*dl_elf_func) (void);
 
@@ -136,6 +145,8 @@
 	unsigned long *_dl_envp;		/* The environment address */
 	ElfW(Addr) relro_addr = 0;
 	size_t relro_size = 0;
+	unsigned long preinit_array;
+	unsigned long preinit_array_size;
 
 	/* Wahoo!!! We managed to make a function call!  Get malloc
 	 * setup so we can use _dl_dprintf() to print debug noise
@@ -769,7 +780,26 @@
 	/* 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.  */
+	preinit_array = _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY];
+	preinit_array_size = _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ];
+	if (preinit_array != 0
+	    && (i = preinit_array_size / sizeof (ElfW(Addr))) > 0) {
+		ElfW(Addr) *addrs;
+		int cnt;
+		addrs = (ElfW(Addr) *) (preinit_array + _dl_loaded_modules->loadaddr);
+		for (cnt = 0; cnt < i; ++cnt) {
+			void (*dl_elf_func) (void);
+			dl_elf_func = (void (*)(void)) (intptr_t) (addrs[cnt]);
+			(*dl_elf_func) ();
+		}
+	}
+
+	/* Run initialization functions for loaded objects.  For the
+	   main executable, they will be run by __libc_csu_init.  */
 	for (i = nlist; i; --i) {
+		unsigned long init_array;
 		tpnt = init_fini_list[i-1];
 		tpnt->init_fini = NULL; /* Clear, since alloca was used */
 		if (tpnt->init_flag & INIT_FUNCS_CALLED)
@@ -785,6 +815,20 @@
 
 			(*dl_elf_func) ();
 		}
+
+		init_array = tpnt->dynamic_info[DT_INIT_ARRAY];
+		if (init_array != 0) {
+			unsigned int j;
+			unsigned int jm;
+			ElfW(Addr) *addrs;
+			jm = tpnt->dynamic_info[DT_INIT_ARRAYSZ] / sizeof (ElfW(Addr));
+			addrs = (ElfW(Addr) *) (init_array + tpnt->loadaddr);
+			for (j = 0; j < jm; ++j) {
+			void (*dl_elf_func) (void);
+			dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
+			(*dl_elf_func) ();
+			}
+		}
 	}
 
 	/* Find the real malloc function and make ldso functions use that from now on */
Index: ldso/libdl/libdl.c
===================================================================
--- ldso/libdl/libdl.c	(revision 13657)
+++ ldso/libdl/libdl.c	(working copy)
@@ -367,6 +367,7 @@
 #ifdef SHARED
 	/* Run the ctors and setup the dtors */
 	for (i = nlist; i; --i) {
+		unsigned long init_array;
 		tpnt = init_fini_list[i-1];
 		if (tpnt->init_flag & INIT_FUNCS_CALLED)
 			continue;
@@ -381,6 +382,20 @@
 				(*dl_elf_func) ();
 			}
 		}
+
+		init_array = tpnt->dynamic_info[DT_INIT_ARRAY];
+		if (init_array != 0) {
+			unsigned int j;
+			unsigned int jm;
+			ElfW(Addr) *addrs;
+			jm = tpnt->dynamic_info[DT_INIT_ARRAYSZ] / sizeof (ElfW(Addr));
+			addrs = (ElfW(Addr) *) (init_array + tpnt->loadaddr);
+			for (j = 0; j < jm; ++j) {
+			void (*dl_elf_func) (void);
+			dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
+			(*dl_elf_func) ();
+			}
+		}
 	}
 #endif /* SHARED */
 
@@ -496,13 +511,26 @@
 	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) ();
+				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) {
+						dl_elf_fini = (int (*)(void)) (intptr_t) array[i];
+						(*dl_elf_fini) ();
+					}
+				}
+
+				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);
Index: libc/sysdeps/linux/arm/crt1.S
===================================================================
--- libc/sysdeps/linux/arm/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/arm/crt1.S	(working copy)
@@ -98,11 +98,11 @@
 .text
 	.globl	_start
 	.type	_start,%function
-	.type	_init,%function
-	.type	_fini,%function
+	.type	__libc_csu_init,%function
+	.type	__libc_csu_fini,%function
 #ifndef __UCLIBC_CTOR_DTOR__
-	.weak	_init
-	.weak	_fini
+	.weak	__libc_csu_init
+	.weak	__libc_csu_fini
 #endif
 
 _start:
@@ -135,11 +135,11 @@
 .L_GOT_OFF:
 	add sl, pc, sl
 
-	ldr ip, .L_GOT+4	/* _fini */
+	ldr ip, .L_GOT+4	/* __libc_csu_fini */
 	ldr a1, [sl, ip]
-	str a1, [sp, #-4]!	/* Push _fini */
+	str a1, [sp, #-4]!	/* Push __libc_csu_fini */
 
-	ldr ip, .L_GOT+8	/* _init */
+	ldr ip, .L_GOT+8	/* __libc_csu_init */
 	ldr a4, [sl, ip]
 	
 	ldr ip, .L_GOT+12	/* main */
@@ -150,13 +150,13 @@
 	b __uClibc_main(PLT)
 #else
 	/* Fetch address of fini */
-	ldr ip, =_fini
+	ldr ip, =__libc_csu_fini
 	/* Push fini */
 	str ip, [sp, #-4]!
 
 	/* Set up the other arguments in registers */
 	ldr a1, =main
-	ldr a4, =_init
+	ldr a4, =__libc_csu_init
 
 	/* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
 
@@ -170,8 +170,8 @@
 #ifdef __PIC__
 .L_GOT:
 	.word	_GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+8)
-	.word _fini(GOT)
-	.word _init(GOT)
+	.word __libc_csu_fini(GOT)
+	.word __libc_csu_init(GOT)
 	.word main(GOT)
 #endif
 
Index: libc/sysdeps/linux/powerpc/crt1.S
===================================================================
--- libc/sysdeps/linux/powerpc/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/powerpc/crt1.S	(working copy)
@@ -35,11 +35,11 @@
 .text
 	.globl	_start
 	.type	_start,%function
-	.type	_init,%function
-	.type	_fini,%function
+	.type	__libc_csu_init,%function
+	.type	__libc_csu_fini,%function
 #ifndef __UCLIBC_CTOR_DTOR__
-	.weak _init
-	.weak _fini
+	.weak __libc_csu_init
+	.weak __libc_csu_fini
 #endif
 	.type	main,%function
 	.type	__uClibc_main,%function
@@ -64,15 +64,15 @@
 			Note:	 using r3 instead of r7, since linux 2.6 clobbers r7 */
 	/* Ok, now run uClibc's main() -- shouldn't return */
 #ifdef __PIC__
-	lwz	r6,_init at got(r31)
-	lwz	r7,_fini at got(r31)
+	lwz	r6,__libc_csu_init at got(r31)
+	lwz	r7,__libc_csu_fini at got(r31)
 	lwz	r3,main at got(r31)
 	b	__uClibc_main at plt
 #else
-	lis     r6,_init at ha	# load top 16 bits
-	addi    r6,r6,_init at l	# load bottom 16 bits
-	lis     r7,_fini at ha	# load top 16 bits
-	addi    r7,r7,_fini at l	# load bottom 16 bits
+	lis     r6,__libc_csu_init at ha	# load top 16 bits
+	addi    r6,r6,__libc_csu_init at l	# load bottom 16 bits
+	lis     r7,__libc_csu_fini at ha	# load top 16 bits
+	addi    r7,r7,__libc_csu_fini at l	# load bottom 16 bits
 	lis     r3,main at ha	# load top 16 bits
 	addi    r3,r3,main at l	# load bottom 16 bits
 	b	__uClibc_main
Index: libc/sysdeps/linux/m68k/crt1.S
===================================================================
--- libc/sysdeps/linux/m68k/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/m68k/crt1.S	(working copy)
@@ -56,11 +56,11 @@
 #include <features.h>
 
 	.text
-	.type	_init,%function
-	.type	_fini,%function
+	.type	__libc_csu_init,%function
+	.type	__libc_csu_fini,%function
 #ifndef __UCLIBC_CTOR_DTOR__
-	.weak	_init
-	.weak	_fini
+	.weak	__libc_csu_init
+	.weak	__libc_csu_fini
 #endif
 	.globl _start
 	.type _start, at function
@@ -85,8 +85,8 @@
 
 	/* Push the address of our own entry points to `.fini' and
 	   `.init'.  */
-	pea _fini
-	pea _init
+	pea __libc_csu_fini
+	pea __libc_csu_init
 
 	pea (%a0)		/* Push second argument: argv.  */
 	move.l %d0, -(%sp)	/* Push first argument: argc.  */
Index: libc/sysdeps/linux/alpha/crt1.S
===================================================================
--- libc/sysdeps/linux/alpha/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/alpha/crt1.S	(working copy)
@@ -26,11 +26,11 @@
 .ent    _start,0
 .type   _start,%function
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type	_init,%function
-.type	_fini,%function
+.type	__libc_csu_init,%function
+.type	__libc_csu_fini,%function
 #else
-.weak   _init
-.weak   _fini
+.weak   __libc_csu_init
+.weak   __libc_csu_fini
 #endif
 .type   __uClibc_main,%function
 /* Stick in a dummy reference to main(), so that if an application
@@ -53,8 +53,8 @@
 	lda	a2, 24(sp)	/* get argv */
 
 	/* Load address of our own entry points to .fini and .init.  */
-	lda	a3, _init
-	lda	a4, _fini
+	lda	a3, __libc_csu_init
+	lda	a4, __libc_csu_fini
 
 	/* Store address of the shared library termination function.  */
 	mov	v0, a5
Index: libc/sysdeps/linux/hppa/crt1.S
===================================================================
--- libc/sysdeps/linux/hppa/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/hppa/crt1.S	(working copy)
@@ -37,8 +37,8 @@
 	.import main, code
 	.import $global$, data
 	.import __uClibc_main, code
-	.import _fini, code
-	.import _init, code
+	.import __libc_csu_fini, code
+	.import __libc_csu_init, code
 
 	/* Have the linker create plabel words
            so we get PLABEL32 relocs and not 21/14 */
@@ -49,9 +49,9 @@
 .Lp__uClibc_main:
 	.word P%__uClibc_main
 .Lp_fini:
-	.word P%_fini
+	.word P%__libc_csu_fini
 .Lp_init:
-	.word P%_init
+	.word P%__libc_csu_init
 
 	.text
 	.align 4
Index: libc/sysdeps/linux/i386/crt1.S
===================================================================
--- libc/sysdeps/linux/i386/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/i386/crt1.S	(working copy)
@@ -60,11 +60,11 @@
 .global _start
 .type   _start,%function
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type   _init,%function
-.type   _fini,%function
+.type   __libc_csu_init,%function
+.type   __libc_csu_fini,%function
 #else
-.weak   _init
-.weak   _fini
+.weak   __libc_csu_init
+.weak   __libc_csu_fini
 #endif
 .type   main,%function
 .type   __uClibc_main,%function
@@ -102,8 +102,8 @@
 	addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx
 
 	/* Push address of our own entry points to .fini and .init.  */
-	pushl _fini at GOT(%ebx)
-	pushl _init at GOT(%ebx)
+	pushl __libc_csu_fini at GOT(%ebx)
+	pushl __libc_csu_init at GOT(%ebx)
 
 	pushl %ecx		/* Push second argument: argv.  */
 	pushl %esi		/* Push first argument: argc.  */
@@ -115,8 +115,8 @@
 	call __uClibc_main at PLT
 #else
 	/* Push address of our own entry points to .fini and .init.  */
-	pushl $_fini
-	pushl $_init
+	pushl $__libc_csu_fini
+	pushl $__libc_csu_init
 
 	pushl %ecx		/* Push second argument: argv.  */
 	pushl %esi		/* Push first argument: argc.  */
Index: libc/sysdeps/linux/nios2/crt1.S
===================================================================
--- libc/sysdeps/linux/nios2/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/nios2/crt1.S	(working copy)
@@ -17,8 +17,8 @@
 
     .global _start
     .type   __start, at function
-    .weak   _init
-    .weak   _fini
+    .weak   __libc_csu_init
+    .weak   __libc_csu_fini
     .type   main, at function
     .type   __uClibc_main, at function
     .type   __h_errno_location, @function
@@ -41,14 +41,14 @@
     ldw r6, 4(sp)		/* argv */
 
     /* load the 4th arg */
-    movhi r7, %hi(_init)
-    ori  r7, r7, %lo(_init)
+    movhi r7, %hi(__libc_csu_init)
+    ori  r7, r7, %lo(__libc_csu_init)
 
     /* Allocate space on the stack for 6-7th arg, reuse 5th space */
     addi sp,sp,-8
     /* push 5-7th args on stack */
-    movhi r8, %hi(_fini)
-    ori  r8, r8, %lo(_fini)
+    movhi r8, %hi(__libc_csu_fini)
+    ori  r8, r8, %lo(__libc_csu_fini)
     stw  r8, 0(sp)
 
     stw  r2, 4(sp)		/* rtld_fini */
Index: libc/sysdeps/linux/frv/crt0.S
===================================================================
--- libc/sysdeps/linux/frv/crt0.S	(revision 13657)
+++ libc/sysdeps/linux/frv/crt0.S	(working copy)
@@ -48,8 +48,8 @@
 #if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__
 	.type __uClibc_main,%function
 #else
-	.weak	_init
-	.weak	_fini
+	.weak	__libc_csu_init
+	.weak	__libc_csu_fini
 	.type	__uClibc_start_main,%function
 #endif
 _start:
@@ -98,10 +98,10 @@
 
 #if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__
 	/* Pass .init and .fini arguments to __uClibc_start_main().  */
-	sethi.p	#gotfuncdeschi(_init), gr11
-	sethi	#gotfuncdeschi(_fini), gr12
-	setlo.p	#gotfuncdesclo(_init), gr11
-	setlo	#gotfuncdesclo(_fini), gr12
+	sethi.p	#gotfuncdeschi(__libc_csu_init), gr11
+	sethi	#gotfuncdeschi(__libc_csu_fini), gr12
+	setlo.p	#gotfuncdesclo(__libc_csu_init), gr11
+	setlo	#gotfuncdesclo(__libc_csu_fini), gr12
 	ld.p	@(gr11, gr17), gr11
 	mov	gr17, gr15
 	ld.p	@(gr12, gr17), gr12
Index: libc/sysdeps/linux/x86_64/crt1.S
===================================================================
--- libc/sysdeps/linux/x86_64/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/x86_64/crt1.S	(working copy)
@@ -62,11 +62,11 @@
 .global _start
 .type   _start,%function
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type   _init,%function
-.type   _fini,%function
+.type   __libc_csu_init,%function
+.type   __libc_csu_fini,%function
 #else
-.weak   _init
-.weak   _fini
+.weak   __libc_csu_init
+.weak   __libc_csu_fini
 #endif
 .type   __uClibc_main,%function
 /* Stick in a dummy reference to main(), so that if an application
@@ -111,8 +111,8 @@
 	movq main at GOTPCREL(%rip), %rdi
 
 	/* setup init/fini address */
-	movq _init at GOTPCREL(%rip), %rcx
-	movq _fini at GOTPCREL(%rip), %r8
+	movq __libc_csu_init at GOTPCREL(%rip), %rcx
+	movq __libc_csu_fini at GOTPCREL(%rip), %r8
 
 	/* start the fun */
 	call __uClibc_main at PLT
@@ -121,8 +121,8 @@
 	movq $main, %rdi
 
 	/* setup init/fini address */
-	movq $_init, %rcx
-	movq $_fini, %r8
+	movq $__libc_csu_init, %rcx
+	movq $__libc_csu_fini, %r8
 
 	/* start the fun */
 	call __uClibc_main
Index: libc/sysdeps/linux/vax/crt1.S
===================================================================
--- libc/sysdeps/linux/vax/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/vax/crt1.S	(working copy)
@@ -40,8 +40,8 @@
 			# where a dynamic linker is involved. So this is
 			# an open FIXME that needs to be addressed at some
 			# time...
-	pushl	$_fini
-	pushl	$_init
+	pushl	$__libc_csu_fini
+	pushl	$__libc_csu_init
 	pushl	%r3	/* Argument pointer */
 	pushl	%r4	/* And the argument count */
 	pushl	$main	/* main() */
Index: libc/sysdeps/linux/cris/crt1.S
===================================================================
--- libc/sysdeps/linux/cris/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/cris/crt1.S	(working copy)
@@ -16,11 +16,11 @@
 .global _start
 .type   _start,%function
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type   _init,%function
-.type   _fini,%function
+.type   __libc_csu_init,%function
+.type   __libc_csu_fini,%function
 #else
-.weak   _init
-.weak   _fini
+.weak   __libc_csu_init
+.weak   __libc_csu_fini
 #endif
 .type   main,%function
 .type   __uClibc_main,%function
@@ -35,7 +35,7 @@
  */
 
 /*
- * Need to call __uClibc_main(main, argc, argv, _init, _fini)
+ * Need to call __uClibc_main(main, argc, argv, __libc_csu_init, __libc_csu_fini)
  */
 
 _start:
@@ -48,11 +48,11 @@
 	Subq 4,$sp
 	move.d $r10,$r9
 	move.d $r11,$r12
-	move.d _fini,$r13
+	move.d __libc_csu_fini,$r13
 	move.d $r13,[$sp]
 	move.d main,$r10
 	move.d $r9,$r11
-	move.d _init,$r13
+	move.d __libc_csu_init,$r13
 	/* Leave control to the libc */
 	jsr __uClibc_main
 .size _start,.-_start
Index: libc/sysdeps/linux/mips/crt1.S
===================================================================
--- libc/sysdeps/linux/mips/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/mips/crt1.S	(working copy)
@@ -72,11 +72,11 @@
 .text
 	.globl	__start
 	.type	__start, at function
-	.type	_init, at function
-	.type	_fini, at function
+	.type	__libc_csu_init, at function
+	.type	__libc_csu_fini, at function
 #ifndef __UCLIBC_CTOR_DTOR__
-	.weak	_init
-	.weak	_fini
+	.weak	__libc_csu_init
+	.weak	__libc_csu_fini
 #endif
 	.type	    main, at function
 	.type	    __uClibc_main, at function
@@ -106,8 +106,8 @@
 
 	and $29, -2 * 4
 	subu $29, 32
-	la $7, _init		/* init */
-	la $8, _fini
+	la $7, __libc_csu_init		/* init */
+	la $8, __libc_csu_fini
 	sw $8, 16($29)		/* fini */
 	sw $2, 20($29)		/* rtld_fini */
 	sw $29, 24($29)		/* stack_end */
Index: libc/sysdeps/linux/nios/crt1.S
===================================================================
--- libc/sysdeps/linux/nios/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/nios/crt1.S	(working copy)
@@ -25,8 +25,8 @@
 
     .global _start
     .type   __start, at function
-    .weak   _init
-    .weak   _fini
+    .weak   __libc_csu_init
+    .weak   __libc_csu_fini
     .type   main, at function
     .type   __uClibc_main, at function
     .type   __h_errno_location, @function
@@ -43,8 +43,8 @@
 	lds	%o1,[%sp, (REGWIN_SZ / 4) + 0]	// main's argc
 	lds	%o2,[%sp, (REGWIN_SZ / 4) + 1]	// main's argv
 
-	MOVIA	%o3, _init at h
-	MOVIA	%o4, _fini at h
+	MOVIA	%o3, __libc_csu_init at h
+	MOVIA	%o4, __libc_csu_fini at h
 	mov	%o5, %i0	/* rtld_fini */
 	mov	%o6, %sp	/* stack_end */
 	MOVIA	%o7, __uClibc_main at h
Index: libc/sysdeps/linux/sparc/crt1.S
===================================================================
--- libc/sysdeps/linux/sparc/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/sparc/crt1.S	(working copy)
@@ -56,11 +56,11 @@
 .global _start
 .type   _start,%function
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type   _init,%function
-.type   _fini,%function
+.type   __libc_csu_init,%function
+.type   __libc_csu_fini,%function
 #else
-.weak   _init
-.weak   _fini
+.weak   __libc_csu_init
+.weak   __libc_csu_fini
 #endif
 .type   __uClibc_main,%function
 /* Stick in a dummy reference to main(), so that if an application
@@ -94,11 +94,11 @@
 
 	/* Load the addresses of the user entry points.  */
 	sethi	%hi(main), %o0
-	sethi	%hi(_init), %o3
-	sethi	%hi(_fini), %o4
+	sethi	%hi(__libc_csu_init), %o3
+	sethi	%hi(__libc_csu_fini), %o4
 	or	%o0, %lo(main), %o0
-	or	%o3, %lo(_init), %o3
-	or	%o4, %lo(_fini), %o4
+	or	%o3, %lo(__libc_csu_init), %o3
+	or	%o4, %lo(__libc_csu_fini), %o4
 #ifdef __PIC__
 	/* Need a little more magic when building PIC to get addr of main */
 	LD	[%l7 + %o0], %o0
Index: libc/sysdeps/linux/sh/crt1.S
===================================================================
--- libc/sysdeps/linux/sh/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/sh/crt1.S	(working copy)
@@ -74,9 +74,9 @@
 L_main:
 	.long   main
 L_init:
-	.long   _init
+	.long   __libc_csu_init
 L_fini:
-	.long   _fini
+	.long   __libc_csu_fini
 L_uClibc_main:
 	.long   __uClibc_main
 L_abort:
Index: libc/sysdeps/linux/bfin/crt1.S
===================================================================
--- libc/sysdeps/linux/bfin/crt1.S	(revision 13657)
+++ libc/sysdeps/linux/bfin/crt1.S	(working copy)
@@ -29,11 +29,11 @@
 .type	___uClibc_main,STT_FUNC;
 
 #if defined(__UCLIBC_CTOR_DTOR__)
-.type   __init,%function
-.type   __fini,%function
+.type   ___libc_csu_init,%function
+.type   ___libc_csu_fini,%function
 #else
-.weak   __init
-.weak   __fini
+.weak   ___libc_csu_init
+.weak   ___libc_csu_fini
 #endif
 
 /*
@@ -41,7 +41,7 @@
 	[ SP ]
 	[argc][argv]...
 
-	Call ___uClibc_main(argc, argv, __init, __fini)
+	Call ___uClibc_main(argc, argv, ___libc_csu_init, ___libc_csu_fini)
 	                     R0    R1     R2    stack
 
 	Before we call main, we want:
@@ -61,11 +61,11 @@
 /*	Copy argv pointer into R1 */
 	R1 = P0;
 
-/*	Load __init into R2 */
-	R2 = __init;
+/*	Load ___libc_csu_init into R2 */
+	R2 = ___libc_csu_init;
 
-/*	Load __fini onto the stack */
-	P0 = __fini;
+/*	Load ___libc_csu_fini onto the stack */
+	P0 = ___libc_csu_fini;
 	[SP--] = P0;
 
 /*	Ok, now run uClibc's main() -- shouldn't return */
Index: libc/misc/internals/Makefile.in
===================================================================
--- libc/misc/internals/Makefile.in	(revision 13657)
+++ libc/misc/internals/Makefile.in	(working copy)
@@ -19,7 +19,8 @@
 libc-a-y+=$(MISC_INTERNALS_OBJ)
 libc-so-y+=$(MISC_INTERNALS_OBJ:.o=.os)
 libc-shared-y+=$(MISC_INTERNALS_OUT)/__uClibc_main.oS
-libc-static-y+=$(MISC_INTERNALS_OUT)/__uClibc_main.o
+libc-static-y+=$(MISC_INTERNALS_OUT)/__uClibc_main.o $(MISC_INTERNALS_OUT)/elf-init.o
+libc-nonshared-y+=$(MISC_INTERNALS_OUT)/elf-init-nonshared.os
 
 libc-multi-y+=$(MISC_INTERNALS_SRC)
 
Index: libc/misc/internals/elf-init-nonshared.c
===================================================================
--- libc/misc/internals/elf-init-nonshared.c	(revision 0)
+++ libc/misc/internals/elf-init-nonshared.c	(revision 0)
@@ -0,0 +1,2 @@
+#define LIBC_NONSHARED
+#include "elf-init.c"
Index: libc/misc/internals/elf-init.c
===================================================================
--- libc/misc/internals/elf-init.c	(revision 0)
+++ libc/misc/internals/elf-init.c	(revision 0)
@@ -0,0 +1,95 @@
+/* Startup support for ELF initializers/finalizers in the main executable.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file. (The GNU Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   Note that people who make modified versions of this file are not
+   obligated to grant this special exception for their modified
+   versions; it is their choice whether to do so. The GNU Lesser
+   General Public License gives permission to release a modified
+   version without this exception; this exception also makes it
+   possible to release a modified version which carries forward this
+   exception.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdio.h>
+
+
+#ifdef __UCLIBC_CTOR_DTOR__
+/* 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;
+
+
+/* These function symbols are provided for the .init/.fini section entry
+   points automagically by the linker.  */
+extern void _init (void);
+extern void _fini (void);
+
+/* These functions are passed to __libc_start_main by the startup code.
+   These get statically linked into each program.  For dynamically linked
+   programs, this module will come from uclibc_nonshared.a and differs from
+   the libc.a module in that it doesn't call the preinit array.  */
+
+void
+__libc_csu_init (void)
+{
+  /* For dynamically linked executables the preinit array is executed by
+     the dynamic linker (before initializing any shared object.  */
+
+#ifndef LIBC_NONSHARED
+  /* 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
+
+  _init ();
+
+  {
+    const size_t size = __init_array_end - __init_array_start;
+    size_t i;
+    for (i = 0; i < size; i++)
+      (*__init_array_start [i]) ();
+  }
+}
+
+void
+__libc_csu_fini (void)
+{
+  size_t i = __fini_array_end - __fini_array_start;
+  while (i-- > 0)
+    (*__fini_array_start [i]) ();
+
+  _fini ();
+}
+#endif

-- 
Joseph S. Myers
joseph at codesourcery.com



More information about the uClibc mailing list