web-dev-qa-db-fra.com

Quelles fonctions gcc ajoute-t-il à l'ELF Linux?

Lorsque vous liez un programme de type hello world en c (ou asm) avec gcc, cela ajoutera des éléments dans le fichier objet exécutable résultant. Je ne connais que l'éditeur de liens dynamique d'exécution et _start point d'entrée mais quel est le type de ces fonctions ajoutées?

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

À quoi servent-ils et à quoi servent-ils? Est-il décrit quelque part? La recherche sur Google n'aide pas.

27
Victor Polevoy

La plupart d'entre elles sont diverses méthodes pour exécuter du code avant ou après le programme "principal" lui-même et la plupart vivent dans crtstuff.c ( https://github.com/gcc-mirror/gcc/blob/master /libgcc/crtstuff.c ). Ils existent pour prendre en charge les fonctionnalités de divers langages de programmation de type C, mais ils sont également accessibles en C. Cela semble peut-être trop compliqué, car certains d'entre eux représentent des bagages hérités et d'autres la variation nécessaire pour prendre en charge les différentes architectures différentes sur lesquelles GCC fonctionne.

Dans votre liste, un par un (ou deux par deux):

00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones

La mémoire transactionnelle est destinée à simplifier la programmation avec des threads. C'est une alternative à la synchronisation basée sur les verrous. Ces routines détruisent et configurent respectivement une table utilisée par la bibliothèque (libitm) qui prend en charge ces fonctions. Plus d'informations sur la MT ici https://gcc.gnu.org/wiki/TransactionalMemory et ici http://pmarlier.free.fr/gcc-tm-tut.html =

0000000000400470 t __do_global_dtors_aux

Exécute tous les destructeurs globaux à la sortie du programme sur les systèmes où .fini_array N'est pas disponible.

0000000000400490 t frame_dummy

Cette fonction réside dans la section .init. Il est défini comme void frame_dummy ( void ) et son but dans la vie est d'appeler __register_frame_info_bases Qui a des arguments. Apparemment, les appels à des fonctions avec des arguments de la section .init Peuvent être peu fiables, d'où cette fonction afin que __register_frame_info_bases Ne soit pas appelé directement à partir de .init section. Les bases d'informations .eh_frame Sont utilisées pour la gestion des exceptions et des fonctionnalités similaires (par exemple, les fonctions déclarées avec __attribute__((cleanup(..)))).

00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini

Ceux-ci exécutent tous les initialiseurs et finaliseurs au niveau du programme (un peu comme des constructeurs/destructeurs similaires pour l'ensemble de votre programme). Si vous définissez des fonctions comme:

void __attribute__ ((constructor)) mefirst () {
    /* ... do something here ... */
}

void __attribute__ ((destructor)) melast () {
    /* ... do something here ... */
}

ils seront appelés respectivement avant et après main() par ces routines. Voir aussi https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

0000000000400554 T _fini

C'est une façon désormais obsolète d'exécuter un destructeur au niveau du programme (au niveau du fichier objet en fait) (une petite information à ce sujet peut être trouvée dans man dlclose). La fonction obsolète correspondante pour les constructeurs est __init.

0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start

Celles-ci marquent la fin et le début de la section .init_array, Qui contient des pointeurs vers tous les initialiseurs au niveau du programme (voir __ libc_csu_init ci-dessus).

0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end

Celles-ci marquent la fin et le début de la section .fini_array, Qui contient des pointeurs vers tous les finaliseurs au niveau du programme (voir __ libc_csu_fini ci-dessus).

[MODIFIER] Quelques notes supplémentaires:

  • Le lien http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html du commentaire de la question du bouffon contient un joli diagramme et un petit exemple de programme illustrant l'ordre général de ces choses ainsi que comment accéder à certaines de ces fonctionnalités à partir de C.

  • Les termes ' ctors' et ' dtors' sont des abréviations pour ' constructeurs' et ' destructeurs 'respectivement.

  • La différence entre les constructeurs/destructeurs globaux et les constructeurs/destructeurs de fichiers objets est plus apparente lorsque votre programme est construit à partir de plusieurs fichiers objets.

  • Les symboles marqués ' [~ # ~] t [~ # ~] ' (__ libc_csu_init, __libc_csu_fini, _fini) sont "globaux" (visibles de l'extérieur), les autres (marqués ' t ') ne le sont pas.

29
John Hascall