À quoi servent les directives CFI dans Gnu Assembler (GAS)?

118

Il semble y avoir une directive .CFI après chaque ligne et il y a aussi large de ces variétés ex., .cfi_startproc, .cfi_endprocEtc .. plus ici .

    .file   "temp.c"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
.globl func
    .type   func, @function
func:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movl    %esi, %eax
    movb    %al, -8(%rbp)
    leave
    ret
    .cfi_endproc
.LFE1:
    .size   func, .-func
    .ident  "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
    .section    .note.GNU-stack,"",@progbits

Je n'ai pas compris le but de ceux-ci.

les griffes
la source
3
description des cfiinstructions d' GNU AS ici
Paschalis
Related : Comment supprimer le «bruit» de la sortie de l'assemblage GCC / clang? , si vous voulez juste les instructions sans les directives. Une bonne façon est de mettre votre code sur gcc.godbolt.org pour voir une belle sortie asm filtrée de différentes versions de divers compilateurs (y compris non-x86), avec une surbrillance de couleur pour faire correspondre les lignes source avec des blocs asm.
Peter Cordes

Réponses:

70

J'ai le sentiment que cela signifie Call Frame Information et qu'il s'agit d'une extension GNU AS pour gérer les trames d'appel. De DeveloperWorks :

Sur certaines architectures, la gestion des exceptions doit être gérée avec les directives Call Frame Information. Ces directives sont utilisées dans l'assembly pour diriger la gestion des exceptions. Ces directives sont disponibles sous Linux sur POWER, si, pour une raison quelconque (portabilité de la base de code, par exemple), les informations de gestion des exceptions générées par GCC ne sont pas suffisantes.

Il semble que ceux-ci soient générés sur certaines plates-formes en fonction du besoin de gestion des exceptions.

Si vous souhaitez les désactiver, veuillez consulter la réponse de David .

Communauté
la source
5
Pouvez-vous aussi dire un mot sur .LFB0, .LFB1, .LFE0, .LFE1
griffes
@claws - Ce sont des étiquettes générées par le compilateur (comme vous pouvez le voir sur le :). Voir stackoverflow.com/a/15285058/4294399
Calculuswhiz
144

Pour les désactiver, utilisez l'option gcc

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm peut être nécessaire également.

David Watson
la source
12
-fno-dwarf2-cfi-asmpeut être nécessaire aussi
technosaurus
Si vous le désactivez pour une sortie asm lisible par l'homme, consultez Comment supprimer le «bruit» de la sortie de l'assembly GCC / clang? pour d'autres options et astuces utiles.
Peter Cordes
30

Les directives CFI sont utilisées pour le débogage. Il permet au débogueur de dérouler une pile. Par exemple: si la procédure A appelle la procédure B qui appelle alors une procédure commune C. La procédure C échoue. Vous voulez maintenant savoir qui a réellement appelé C, puis vous voudrez peut-être savoir qui a appelé B.

Un débogueur peut dérouler cette pile en utilisant le pointeur de pile (% rsp) et enregistrer% rbp, mais il doit savoir comment les trouver. C'est là qu'interviennent les directives de la FCI.

movq    %rsp, %rbp
.cfi_def_cfa_register 6

donc la dernière ligne ici lui indique que "l'adresse de trame d'appel" est maintenant dans le registre 6 (% rbp)

Graham Stott
la source
2
Mais l'utilisation de la gestion des exceptions de cfi devrait être plus fréquente que le débogage, je pense.
osgx
6
En fait, CFA signifie "adresse de trame canonique". Regardez ici .
Cameron
1
Les directives CFI permettent le déroulement de la pile même pour le code compilé avec -fomit-frame-pointer, comme alternative à RBP (qui est activé par défaut avec gcc ou clang -O1et plus). Il est utilisé par la gestion des exceptions C ++ ainsi que par les débogueurs / profileurs. Dans le code avec des pointeurs de trame RBP traditionnels, la valeur RBP actuelle pointe toujours vers une valeur RBP enregistrée, et qui pointe vers la précédente formant une liste liée. Il n'y a pas besoin de CFI dans ce cas. (Bien que dans les fonctions qui utilisent un pointeur de cadre, CFI cfa_register évite d'avoir besoin de plus de métadonnées pour chaque changement de RSP, comme vous le montrez.)
Peter Cordes
2

Pour les désactiver, g ++ a besoin -fno-exceptionsde ce qui a été mentionné précédemment -fno-asynchronous-unwind-tables, à condition que vous n'utilisiez pas d'exceptions.

iw4h
la source