Что такое .cfi и .LFE в ассемблерном коде, созданном GCC из программы на c ++? - PullRequest
31 голосов
/ 25 августа 2010

У меня есть следующий код C ++

int factorial(int n){

    if(n==0){
        return 1;
    }
    return n*factorial(n-1);

}

int main(void){
    factorial(5);
    return 0;
}

Когда я создаю файл сборки с помощью g ++ -S factorial.cpp, я получаю следующее:

    .file   "tail_call_opt.cpp"
    .text
.globl _Z9factoriali
    .type   _Z9factoriali, @function
_Z9factoriali:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    cmpl    $0, 8(%ebp)
    jne .L2
    movl    $1, %eax
    jmp .L3
.L2:
    movl    8(%ebp), %eax
    subl    $1, %eax
    movl    %eax, (%esp)
    call    _Z9factoriali
    imull   8(%ebp), %eax
.L3:
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   _Z9factoriali, .-_Z9factoriali
.globl main
    .type   main, @function
main:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    $5, (%esp)
    call    _Z9factoriali
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE1:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

Я могу следовать большинствуэто, но какова цель частей .cfi и .LFE?Где я могу узнать больше о сборке, производимой gcc?

1 Ответ

52 голосов
/ 26 августа 2010

Эти директивы говорят газу испускать теги информации о кадре вызова Dwarf, которые, очевидно, используются для восстановления обратной трассировки стека, когда отсутствует указатель кадра. В вашем случае указатель кадра присутствует, поэтому я думаю, что он может быть использован для выполнения раскручивания во время обработки исключений. Такой механизм имеет меньше накладных расходов, чем старый sjlj (setjump / longjump). См. здесь , а также связанную спецификацию Dwarf.

Что касается меток .Lxx, префикс .L указывает, что метка является локальной для этого файла и поэтому не будет конфликтовать с метками с одинаковыми именами в других файлах. GCC обычно использует .L для автоматически сгенерированных меток. В этом случае, скорее всего, «FB» означает «начало функции», а «FE» означает «конец функции».

...