¿Para qué se utilizan las directivas CFI en Gnu Assembler (GAS)?

118

Parece haber una directiva .CFI después de cada línea y también hay una gran variedad de estas, por ejemplo .cfi_startproc, .cfi_endprocetc., más aquí .

    .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

No entendí el propósito de estos.

garras
fuente
3
descripción de las cfiinstrucciones de GNU AS aquí
Paschalis
relacionado: ¿Cómo eliminar el "ruido" de la salida del ensamblaje GCC / clang? , si solo desea las instrucciones sin las directivas. Una buena forma es poner su código en gcc.godbolt.org para ver un buen resultado ASM filtrado de varias versiones de varios compiladores (incluidos los que no son x86), con resaltado de color para hacer coincidir las líneas de origen con los bloques ASM.
Peter Cordes

Respuestas:

70

Tengo la sensación de que significa información de tramas de llamadas y es una extensión GNU AS para administrar tramas de llamadas. Desde DeveloperWorks :

En algunas arquitecturas, el manejo de excepciones debe administrarse con directivas de información de tramas de llamada. Estas directivas se utilizan en el ensamblado para dirigir el manejo de excepciones. Estas directivas están disponibles en Linux en POWER si, por cualquier motivo (portabilidad del código base, por ejemplo), la información de manejo de excepciones generada por GCC no es suficiente.

Parece que estos se generan en algunas plataformas según la necesidad de manejo de excepciones.

Si desea desactivarlos, consulte la respuesta de David .

Comunidad
fuente
5
También puedes decir algo sobre .LFB0, .LFB1, .LFE0, .LFE1
garras
@claws: son etiquetas generadas por el compilador (como puede ver en :). Ver stackoverflow.com/a/15285058/4294399
Calculuswhiz
144

Para deshabilitarlos, use la opción gcc

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm también puede ser necesario.

David Watson
fuente
12
-fno-dwarf2-cfi-asmtambién puede ser necesario
technosaurus
Si lo está deshabilitando para la salida ASM legible por humanos, consulte ¿Cómo eliminar el "ruido" de la salida del ensamblaje GCC / clang? para conocer otras opciones y trucos útiles.
Peter Cordes
30

Las directivas CFI se utilizan para depurar. Permite al depurador desenrollar una pila. Por ejemplo: si el procedimiento A llama al procedimiento B, que luego llama a un procedimiento común C. El procedimiento C falla. Ahora desea saber quién llamó realmente a C y luego puede querer saber quién llamó a B.

Un depurador puede desenrollar esta pila usando el puntero de pila (% rsp) y registrar% rbp, sin embargo, necesita saber cómo encontrarlos. Ahí es donde entran las directivas CFI.

movq    %rsp, %rbp
.cfi_def_cfa_register 6

por lo que la última línea aquí le dice que la "Dirección del marco de llamada" ahora está en el registro 6 (% rbp)

Graham Stott
fuente
2
Pero el uso de manejo de excepciones de cfi debería ser más frecuente que la depuración, creo.
osgx
6
En realidad, CFA significa "dirección de marco canónico". Vea aquí .
Cameron
1
Las directivas CFI permiten desenrollar la pila incluso para el código compilado con -fomit-frame-pointer, como alternativa a RBP (que está activado de forma predeterminada con gcc o clang -O1y superior). Es utilizado por el manejo de excepciones de C ++, así como por los depuradores / perfiladores. En el código con punteros de trama RBP tradicionales, el valor RBP actual siempre apunta a un valor RBP guardado, y eso apunta al anterior formando una lista vinculada. En ese caso, no es necesario CFI. (Aunque en las funciones que usan un puntero de marco, CFI cfa_register evita la necesidad de más metadatos para cada cambio de RSP, como está mostrando).
Peter Cordes
2

Para deshabilitarlos, g ++ necesita -fno-exceptionsjunto con lo mencionado anteriormente -fno-asynchronous-unwind-tables, siempre que no use excepciones.

iw4h
fuente