[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