[patch] init_array/fini_array support

Joseph S. Myers joseph at codesourcery.com
Fri Jan 20 13:40:25 UTC 2006


On Fri, 20 Jan 2006, Peter S. Mazinger wrote:

> > +void
> > +__libc_csu_fini (void)
> > +{
> 
> this is guarded by LIBC_NONSHARED in glibc, shouldn't we do the same?

No, the comment in glibc is "We run the executable's destructor now just 
like any other." and I don't think this is the case for uClibc's ld.so (if 
it were, we'd already have been running _fini twice).

Here is a revised patch that I think addresses the comments made.  It 
doesn't condition any of ld.so/libdl on __UCLIBC_CTOR_DTOR__ because that 
appears to be a separate issue that should be patched separately, applying 
to the existing DT_INIT etc. support as well as to the new DT_INIT_ARRAY 
etc. support.

Index: ldso/ldso/ldso.c
===================================================================
--- ldso/ldso/ldso.c	(revision 13445)
+++ ldso/ldso/ldso.c	(working copy)
@@ -105,6 +105,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);
 
@@ -134,6 +143,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
@@ -767,7 +778,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)
@@ -783,6 +813,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 13445)
+++ ldso/libdl/libdl.c	(working copy)
@@ -370,6 +370,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;
@@ -384,6 +385,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 */
 
@@ -499,13 +514,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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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/mips/crt1.S
===================================================================
--- libc/sysdeps/linux/mips/crt1.S	(revision 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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 13445)
+++ 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/misc/internals/Makefile.in
===================================================================
--- libc/misc/internals/Makefile.in	(revision 13445)
+++ 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