When linking a hello-world-like program in c (or asm) with gcc
it will add some stuff into the result executable object file. I know only about runtime dynamic link
Most of these are various methods to execute code before or after the "main" program itself and most live in crtstuff.c
( https://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c ).
They exist to support features of various C-like programming languages, but they can be accessed in C as well. It perhaps seems over complicated because some of these represent legacy baggage and some the variation needed to support the various different architectures that GCC runs on.
From your list, one by one (or two by two):
00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones
Transactional memory is intended to make programming with threads simpler. It is an alternative to lock-based synchronization. These routines tear down and setup, respectively, a table used by the library (libitm) which supports these functions. More info on TM here https://gcc.gnu.org/wiki/TransactionalMemory and here http://pmarlier.free.fr/gcc-tm-tut.html
0000000000400470 t __do_global_dtors_aux
Runs all the global destructors on exit from the program on systems where .fini_array
is not available.
0000000000400490 t frame_dummy
This function lives in the .init
section. It is defined as void frame_dummy ( void )
and its whole point in life is to call __register_frame_info_bases
which has arguments. Apparently calls to functions with arguments from the .init
section can be unreliable, hence this function so __register_frame_info_bases
doesn't get called directly from the .init section
.
The .eh_frame
info bases are used for exception handling and similar features (e.g. functions declared with __attribute__((cleanup(..)))
).
00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini
These run any program-level initializers and finalizers (kind of like constructors/destructors for your whole program). If you define functions like:
void __attribute__ ((constructor)) mefirst () {
/* ... do something here ... */
}
void __attribute__ ((destructor)) melast () {
/* ... do something here ... */
}
they will be called before and after main()
respectively by these routines.
See also https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
0000000000400554 T _fini
This is a now-deprecated way to run a program-level (object file-level actually) destructor (a little info on this can be found in man dlclose
).
The corresponding obsolete function for constructors is __init
.
0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start
These mark the end and start of the .init_array
section, which contains pointers to all the program-level initializers (see __libc_csu_init above).
0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end
These mark the end and start of the .fini_array
section, which contains pointers to all the program-level finalizers (see __libc_csu_fini above).
[EDIT] Some Additional Notes:
The link http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html (wayback machine) from Jester's question comment contains a nice diagram and a small sample program illustrating the overall order these things run as well as how to access some of these features from C.
The terms 'ctors' and 'dtors' are abbreviations for 'constructors' and 'destructors' respectively.
The difference between global constructors/destructors and object-file constructors/destructors is most apparent when your program is constructed from multiple object files.
The symbols marked 'T' (__libc_csu_init, __libc_csu_fini, _fini) are "global" (externally visible), the remainer (marked 't') are not.