Here's a simple program:
void __attribute__ ((constructor)) dumb_constructor(){}
void __attribute__ ((destructor)) dumb_destructor(){}
int main() {}
I compile it with the following flags:
g++ -O0 -fverbose-asm -no-pie -g -o main main.cpp
I check with gdb that __libc_csu_init is calling the function I tagged w/ constructor:
Breakpoint 1, dumb_constructor () at main.cpp:1
1 void __attribute__ ((constructor)) dumb_constructor(){}
(gdb) bt
#0 dumb_constructor () at main.cpp:1
#1 0x000000000040116d in __libc_csu_init ()
#2 0x00007ffff7abcfb0 in __libc_start_main () from /usr/lib/libc.so.6
#3 0x000000000040104e in _start ()
and I assume that destructor attribute would mean dumb_destructor() would be called during __libc_csu_fini, but that's not happening:
Breakpoint 1, dumb_destructor () at main.cpp:3
3 void __attribute__ ((destructor)) dumb_destructor(){}
(gdb) bt
#0 dumb_destructor () at main.cpp:3
#1 0x00007ffff7fe242b in _dl_fini () from /lib64/ld-linux-x86-64.so.2
#2 0x00007ffff7ad4537 in __run_exit_handlers () from /usr/lib/libc.so.6
#3 0x00007ffff7ad46ee in exit () from /usr/lib/libc.so.6
#4 0x00007ffff7abd02a in __libc_start_main () from /usr/lib/libc.so.6
#5 0x000000000040104e in _start ()
I sanity checked that __libc_csu_fini really isn't doing anything with objdump and it really is a stub:
0000000000401190 <__libc_csu_fini>:
401190: f3 0f 1e fa endbr64
401194: c3 ret
Why do we call this _dl_fini? What is _dl_fini? Why is it being inconsistent and not calling __libc_csu_fini?