Pourquoi GCC programme C compilé besoins .eh_frame section?
Test est sur 32 bits x86 Linux avec gcc
4.6.3
Lors de l'utilisation de gcc
pour compiler un C
programme et à l'aide de readelf
pour vérifier la section info,
Je peux voir le .eh_frame
section et .eh_frame_hdr
sections à l'intérieur.
Par exemple, voici la section info de binaire programme Perlbench
.
readelf -S perlbench
There are 28 section headers, starting at offset 0x102e48:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000044 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481f0 0001f0 0007b0 10 A 6 1 4
[ 6] .dynstr STRTAB 080489a0 0009a0 0003d6 00 A 0 0 1
[ 7] .gnu.version VERSYM 08048d76 000d76 0000f6 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048e6c 000e6c 0000a0 00 A 6 2 4
[ 9] .rel.dyn REL 08048f0c 000f0c 000028 08 A 5 0 4
[10] .rel.plt REL 08048f34 000f34 000388 08 A 5 12 4
[11] .init PROGBITS 080492bc 0012bc 00002e 00 AX 0 0 4
[12] .plt PROGBITS 080492f0 0012f0 000720 04 AX 0 0 16
[13] .text PROGBITS 08049a10 001a10 0cf86c 00 AX 0 0 16
[14] .fini PROGBITS 0811927c 0d127c 00001a 00 AX 0 0 4
[15] .rodata PROGBITS 081192a0 0d12a0 017960 00 A 0 0 32
[16] .eh_frame_hdr PROGBITS 08130c00 0e8c00 003604 00 A 0 0 4
[17] .eh_frame PROGBITS 08134204 0ec204 01377c 00 A 0 0 4
[18] .ctors PROGBITS 08148f0c 0fff0c 000008 00 WA 0 0 4
[19] .dtors PROGBITS 08148f14 0fff14 000008 00 WA 0 0 4
[20] .jcr PROGBITS 08148f1c 0fff1c 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08148f20 0fff20 0000d0 08 WA 6 0 4
[22] .got PROGBITS 08148ff0 0ffff0 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 08148ff4 0ffff4 0001d0 04 WA 0 0 4
[24] .data PROGBITS 081491e0 1001e0 002b50 00 WA 0 0 32
[25] .bss NOBITS 0814bd40 102d30 002b60 00 WA 0 0 32
[26] .comment PROGBITS 00000000 102d30 00002a 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 102d5a 0000ec 00 0 0 1
Dans ma compréhension, ces deux sections sont utilisées pour la gestion des exceptions, c'produire des tableaux qui décrivent la façon de détendre la pile.
Mais c'est pour C++
programme, ils utilisent eh_frame
et gcc_exception_table
sections pour gérer les exceptions, alors pourquoi ne compilateur mettre le eh_frame
et eh_frame_hdr
sections à l'intérieur des ELF
compilées à partir de C
programme?
- x86-64 ABI mandats
.eh frames
partout exacte. Cela a été ajoutée pour permettre le déroulement de la pile partout où cela est nécessaire à l'échelle du système dans certains cas, comme dans des outils de profilage. GCC donc sur x86_64 par défaut HEIN cadre de la génération et de la tentative d'en faire partout exacte, alors que sur la plupart des autres ABIs la valeur par défaut HEIN cadre génération seulement lorsque EH cadre est nécessaire et il est précis uniquement dans les points de programme qui pourrait déclencher HEIN et donc de déroulement. - Je soupçonne
gcc
utilise aussi à mettre en œuvre__attribute__((cleanup(..)))
. - double possible de What de l'utilisation de l' .eh_frame section dans les programmes en C?
- "référence à cette question?" Je ne comprends pas ce que tu veux dire. Entendez-vous les commentaires? Pourquoi les questions sont différentes? J'ai peut-être tort. La fermeture de l'inverse est une autre possibilité: c'est un peu mieux posés, donc, mais l'autre est plus, choix difficile. Sur nom d'utilisateur, le congé de discussion pour la méta ou twitter. Des acclamations.
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, l'origine, ce fut en grande partie politique - les personnes qui ont ajouté NAIN à base de déroulage (
.eh_frame
) voulais que ce soit une caractéristique qui est toujours là donc, il pourrait être utilisé pour la mise en œuvre de toutes sortes de choses autres que les exceptions C++, y compris:backtrace()
__attribute__((__cleanup__(f)))
__builtin_return_address(n)
, pourn>0
pthread_cleanup_push
, mis en œuvre en termes de__attribute__((__cleanup__(f)))
Toutefois, si vous n'avez pas besoin de toutes ces choses,
.eh_frame
est quelque chose comme un de 15 à 30% d'augmentation de.text
taille avec aucun avantage. Vous pouvez désactiver la génération de.eh_frame
avec-fno-asynchronous-unwind-tables
pour chaque unités de traduction, et ce la plupart du temps élimine la taille du prix, même si vous avez encore un peu de gauche, plus à venir à partir decrtbegin.o
, etc. Vous ne peut pas bande avec lastrip
commande plus tard; depuis.eh_frame
est une section qui vit dans l'chargé une partie du programme (c'est le point de l'ensemble), de décapage, il modifie le fichier binaire de façon à briser lors de l'exécution. Voir https://sourceware.org/bugzilla/show_bug.cgi?id=14037 pour un exemple de la façon dont les choses peuvent se briser.Noter que le NAIN tables sont également utilisés à des fins de débogage, mais pour cela ils n'ont pas besoin d'être dans la chargeable partie du programme. À l'aide de
-fno-asynchronous-unwind-tables
ne sera pas briser le débogage, parce que tant que-g
est également passé au compilateur, les tables toujours générée; ils sont juste stocké dans un autre, non-chargeables, pelable section du binaire,.debug_frame
.crtbegin.o
contient pas de FCI, au moins sur RedHat et Ubuntu. Les restes seraient le plus susceptibles de provenir de la FCI pour les__libc_csu_init
et__libc_csu_fini
. Ceux qui ne sont pas danscrtbegin.o
, mais plutôt dans le non-partie commune de la GLIBClibc_nonshared.a
.eh_frame
dans la sortie lorsque vous n'utilisez pas la glibc, donc il doit y avoir certains viennent d'ailleurs aussi. Je pensais que c'étaitcrtbegin.o
mais je me trompe peut-être.strip
commande?" Je pense qu'il peut être supprimé sans risque (et le fichier exécutable sera devenu plus petit) si aucune des caractéristiques ci-dessus sont utilisés dans le fichier exécutable. Suis-je le droit?eh_frame
est un GCC spécifié fonctionnalité? J'ai essayé d'utiliserclang
etgcc
pour compiler un morceau de code C. Leeh_frame
section généré par GCC est autour de0x5cfc
alors qu'il est seulementa4
pourclang
.-fno-omit-frame-pointer
permet de réduire les eh_frame sensiblement la taille, et gcc devs ont envisagé d'essayer d'avoir gcc utilisation rbp comme un pointeur de cadre dans des fonctions où il ne sera pas un ralentissement.longjmp
, et de la propagation d'une exception serait l'équivalent delongjmp
. Si le code C++ à l'aide d'exceptions est appelé comme un rappel à partir de C, la fonction de rappel doit attraper toutes les exceptions et les traduire en erreur renvoie au C de l'appelant.malloc
échouera plus tôt.