Para que são usadas as diretivas CFI no Gnu Assembler (GAS)?

118

Parece haver uma directiva .CFI após cada linha e também há grande variedades destes ex., .cfi_startproc, .cfi_endprocEtc .. mais aqui .

    .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

Eu não entendi o propósito disso.

garras
fonte
3
descrição das cfiinstruções GNU AS aqui
Paschalis
relacionado: Como remover “ruído” da saída do conjunto GCC / clang? , se você quiser apenas as instruções sem as diretivas. Uma boa maneira é colocar seu código em gcc.godbolt.org para ver uma boa saída de conjunto filtrada de várias versões de vários compiladores (incluindo não-x86), com destaque de cor para combinar linhas de origem com blocos de conjunto.
Peter Cordes,

Respostas:

70

Tenho a sensação de que significa Call Frame Information e é uma extensão GNU AS para gerenciar call frames. De DeveloperWorks :

Em algumas arquiteturas, o tratamento de exceções deve ser gerenciado com as diretivas Call Frame Information. Essas diretivas são usadas no assembly para direcionar o tratamento de exceções. Essas diretivas estão disponíveis no Linux on POWER, se, por algum motivo (portabilidade da base de código, por exemplo), as informações de tratamento de exceções geradas pelo GCC não forem suficientes.

Parece que eles são gerados em algumas plataformas, dependendo da necessidade de tratamento de exceções.

Se você deseja desativá-los, consulte a resposta de David .

Comunidade
fonte
5
Você também pode dizer uma palavra sobre .LFB0, .LFB1, .LFE0, .LFE1
garras de
@claws - Esses são rótulos gerados pelo compilador (como você pode ver no :). Consulte stackoverflow.com/a/15285058/4294399
Calculuswhiz
144

Para desabilitá-los, use a opção gcc

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm pode ser necessário também.

David Watson
fonte
12
-fno-dwarf2-cfi-asmpode ser necessário também
tecnossauro
Se você estiver desativando para saída asm legível por humanos, consulte Como remover "ruído" da saída do assembly GCC / clang? para outras opções e truques úteis.
Peter Cordes
30

As diretivas CFI são usadas para depuração. Ele permite que o depurador desenrole uma pilha. Por exemplo: se o procedimento A chama o procedimento B, que então chama um procedimento comum C. O procedimento C falha. Agora você deseja saber quem realmente ligou para C e, em seguida, pode querer saber quem ligou para B.

Um depurador pode desenrolar essa pilha usando o ponteiro da pilha (% rsp) e registrar% rbp, entretanto, ele precisa saber como encontrá-los. É aí que entram as diretivas CFI.

movq    %rsp, %rbp
.cfi_def_cfa_register 6

então a última linha aqui informa que o "endereço do quadro de chamada" está agora no registro 6 (% rbp)

Graham Stott
fonte
2
Mas o uso de tratamento de exceção de cfi deve ser mais frequente do que depuração, eu acho.
osgx
6
Na verdade, CFA significa "endereço de quadro canônico". Veja aqui .
Cameron
1
As diretivas CFI permitem o desdobramento da pilha até mesmo para código compilado com -fomit-frame-pointer, como uma alternativa para RBP (que é ativado por padrão com gcc ou clang -O1e superior). É usado pelo tratamento de exceções C ++, bem como depuradores / criadores de perfil. No código com ponteiros de quadro RBP tradicionais, o valor RBP atual sempre aponta para um valor RBP salvo, e isso aponta para o anterior formando uma lista vinculada. Não há necessidade de CFI nesse caso. (Embora em funções que usam um ponteiro de frame, o CFI cfa_register evita a necessidade de mais metadados para cada alteração do RSP, como você está mostrando.)
Peter Cordes
2

Para desabilitá-los, o g ++ precisa -fno-exceptionsjunto com o mencionado anteriormente -fno-asynchronous-unwind-tables, desde que você não use exceções.

iw4h
fonte