ps2 - ¿Qué funciones agrega gcc al linux ELF?
readelf (1)
Al vincular un programa similar a hello-world en c (o asm) con gcc
, se agregarán algunas cosas al archivo de objeto ejecutable resultante. Solo conozco el enlazador dinámico en tiempo de ejecución y el punto de entrada de _start
pero ¿cuál es el tipo de estas funciones agregadas?
00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones
0000000000400470 t __do_global_dtors_aux
0000000000400490 t frame_dummy
00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini
0000000000400554 T _fini
0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start
0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end
¿Qué son y para qué? ¿Se describe en alguna parte? Googlear no ayuda.
La mayoría de estos son varios métodos para ejecutar código antes o después del programa "principal" y la mayoría de ellos en vivo en crtstuff.c
( https://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c ) . Existen para admitir características de varios lenguajes de programación tipo C, pero también se puede acceder a ellos en C. Quizás parezca demasiado complicado porque algunos de ellos representan un equipaje heredado y, en parte, la variación necesaria para soportar las diferentes arquitecturas diferentes en las que se ejecuta GCC.
De su lista, uno por uno (o dos por dos):
00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones
La memoria transaccional está destinada a simplificar la programación con subprocesos. Es una alternativa a la sincronización basada en bloqueo. Estas rutinas derriban y configuran, respectivamente, una tabla utilizada por la biblioteca (libitm) que admite estas funciones. Más información sobre TM aquí https://gcc.gnu.org/wiki/TransactionalMemory y aquí http://pmarlier.free.fr/gcc-tm-tut.html
0000000000400470 t __do_global_dtors_aux
Ejecuta todos los destructores globales al salir del programa en sistemas donde .fini_array
no está disponible.
0000000000400490 t frame_dummy
Esta función vive en la sección .init
. Se define como void frame_dummy ( void )
y su punto en la vida es llamar a __register_frame_info_bases
que tiene argumentos. Aparentemente, las llamadas a funciones con argumentos de la sección .init
pueden ser poco confiables, por lo tanto, esta función para que __register_frame_info_bases
no sea llamada directamente desde la .init section
. Las bases de información .eh_frame
se utilizan para el manejo de excepciones y características similares (por ejemplo, funciones declaradas con __attribute__((cleanup(..)))
).
00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini
Estos ejecutan cualquier inicializador y finalizador a nivel de programa (tipo de constructores / destructores similares para todo el programa). Si define funciones como:
void __attribute__ ((constructor)) mefirst () {
/* ... do something here ... */
}
void __attribute__ ((destructor)) melast () {
/* ... do something here ... */
}
serán llamadas antes y después de main()
respectivamente por estas rutinas. Consulte también https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
0000000000400554 T _fini
Esta es una forma ahora en desuso de ejecutar un destructor a nivel de programa (en realidad, a nivel de archivo de objeto) (se puede encontrar una pequeña información sobre esto en el man dlclose
). La función obsoleta correspondiente para los constructores es __init
.
0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start
Estos marcan el final y el inicio de la sección .init_array
, que contiene punteros a todos los inicializadores a nivel de programa (consulte __libc_csu_init más arriba).
0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end
Estos marcan el final y el inicio de la sección .fini_array
, que contiene punteros a todos los finalizadores a nivel de programa (consulte __libc_csu_fini más arriba).
[EDITAR] Algunas notas adicionales:
El enlace http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html del comentario de la pregunta de Jester contiene un bonito diagrama y un pequeño programa de muestra que ilustra el orden general en que se ejecutan estas cosas y cómo acceder a algunas de estas funciones. desde C.
Los términos '' ctors '' y '' dtors '' son abreviaturas de '' constructores '' y '' destructores '' respectivamente.
La diferencia entre constructores / destructores globales y constructores / destructores de archivos de objetos es más evidente cuando su programa se construye a partir de múltiples archivos de objetos.
Los símbolos marcados con '' T '' ( __libc_csu_init, __libc_csu_fini, _fini ) son "globales" (visibles externamente), el resto (marcado como '' t '') no lo son.