gcc behavior of init priority of .ctors and .dtors section
Date: Thu, 16 May 2024 12:06:46 UTC
Hi, I'm recently working on https://reviews.freebsd.org/D45194 and got noticed that gcc behaves weirdly. A simple source file to demonstrate that. ``` # cat ctors.c #include <stdio.h> __attribute__((constructor(101))) void init_101() { puts("init 1"); } __attribute__((constructor(65535))) void init_65535() { puts("init 3"); } __attribute__((constructor)) void init() { puts("init 4"); } __attribute__((constructor(65535))) void init_65535_2() { puts("init 5"); } __attribute__((constructor(65534))) void init_65534() { puts("init 2"); } int main() { puts("main"); } __attribute__((destructor(65534))) void fini_65534() { puts("fini 2"); } __attribute__((destructor(65535))) void fini_65535() { puts("fini 3"); } __attribute__((destructor)) void fini() { puts("fini 4"); } __attribute__((destructor(65535))) void fini_65535_2() { puts("fini 5"); } __attribute__((destructor(101))) void fini_101() { puts("fini 1"); } # clang ctors.c && ./a.out init 1 init 2 init 3 init 4 init 5 main fini 5 fini 4 fini 3 fini 2 fini 1 ``` clang with the option -fno-use-init-array and run will produce the same result, which is what I expected. gcc13 from ports ``` # gcc ctors.c && ./a.out init 1 init 2 init 5 init 4 init 3 main fini 3 fini 4 fini 5 fini 2 fini 1 ``` The above order is not expected. I think clang's one is correct. Further hacking with readelf shows that clang produces the right order of section .rela.ctors but gcc does not. ``` # clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 'Relocation section with addend (.rela.ctors)' -A5 > clang.txt # gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with addend (.rela.ctors)' -A5 > gcc.txt # diff clang.txt gcc.txt 3,5c3,5 < 000000000000 000800000001 R_X86_64_64 0000000000000060 init_65535_2 + 0 < 000000000008 000700000001 R_X86_64_64 0000000000000040 init + 0 < 000000000010 000600000001 R_X86_64_64 0000000000000020 init_65535 + 0 --- > 000000000000 000600000001 R_X86_64_64 0000000000000011 init_65535 + 0 > 000000000008 000700000001 R_X86_64_64 0000000000000022 init + 0 > 000000000010 000800000001 R_X86_64_64 0000000000000033 init_65535_2 + 0 ``` The above show clearly gcc produces the wrong order of section `.rela.ctors`. Is that expected behavior ? I have not tried Linux version of gcc. Best regards, Zhenlei