This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Problem of execution order of entries in .fini_array


Hi,

I am debugging one GCC-4.4 dejaGNU test case that fails on ARM-eabi target.
I build the toolchain with newlib and run the test on GNU arm-sim simulator.

The test case gcc/testsuite/gcc.dg/initpri1.c is testing whether the
compiler and linker process the constructor attribute and destructor
attribute correctly.

In initpri1.c, we see
void c1() __attribute__((constructor (500)));
void c2() __attribute__((constructor (700)));
void c3() __attribute__((constructor (600)));
void d1() __attribute__((destructor (500)));
void d2() __attribute__((destructor (700)));
void d3() __attribute__((destructor (600)));
void cd4() __attribute__((constructor (800), destructor (800)));

The correct execution order should be:
c1() -> c3() -> c2() -> cd4() -> cd4() -> d2() -> d3() -> d1()

However, on ARM-eabi target (GCC-4.4 + binutils-2.19 + newlib), the
sequence is wrong:
c1() -> c3() -> c2() -> cd4() -> d1() -> d3() -> d2() -> cd4()

I have checked both the assembly file (generated by arm-eabi-gcc -S)
and object dumped file (generated by arm-eabi-objdump -D). GCC puts
all constructors in .init_array section in increasing order and all
destructors in .fini_array section in increasing order.

Disassembly of section .init_array:

00013b10 <__init_array_start>:
  13b10:       000081b8        .word   0x000081b8     <----   c1
  13b14:       00008260        .word   0x00008260     <----   c3
  13b18:       0000820c        .word   0x0000820c     <----   c2
  13b1c:       000083b0        .word   0x000083b0     <---    cd4

00013b20 <__frame_dummy_init_array_entry>:
  13b20:       00008058        .word   0x00008058   <--- frame_dummy

Disassembly of section .fini_array:

00013b24 <__do_global_dtors_aux_fini_array_entry>:
  13b24:       00008018        .word   0x00008018    <-- __do_global_dtors_aux
  13b28:       000082b4        .word   0x000082b4   <--- d1
  13b2c:       0000834c        .word   0x0000834c   <---  d3
  13b30:       00008300        .word   0x00008300  <---  d2
  13b34:       000083b0        .word   0x000083b0  <---  cd4

However, newlib accesses entries in .fini_array in increasing order
too. So that we see a wrong order of destructors.

000084f8 <__libc_init_array>:
 it calls entries in <__init_array_start> in increasing order.

000084b0 <__libc_fini_array>:
 it calls entries in <__do_global_dtors_aux_fini_array_entry> in
increasing order.

000080ac <_mainCRTStartup>:
 ...
 call <atexit> with argument <__libc_fini_array>
 call <__libc_init_array>
 call <main>
 call <exit>

After discussing with a few GCC gurus, I was told this maybe a bug in
newlib. Because ELF specification
(http://www.caldera.com/developers/gabi/2003-12-17/ch5.dynamic.html#init_fini)
says:
"The functions pointed to in the arrays specified by DT_INIT_ARRAY and
by DT_PREINIT_ARRAY are executed by the dynamic linker in the same
order in which their addresses appear in the array; those specified by
DT_FINI_ARRAY are executed in reverse order."

The code in newlib which takes care of the fini_array is in
newlib/libc/misc/init.c:

/* Run all the cleanup routines.  */
void
__libc_fini_array (void)
{
  size_t count;
  size_t i;

  count = __fini_array_end - __fini_array_start;
  for (i = 0; i < count; i++)     <--------- This is the place!
    __fini_array_start[i] ();

  _fini ();
}

Should we change the access order or fini_array?

Thanks,
Jing


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]