Для чего используются директивы CFI в Gnu Assembler (GAS)?

118

Там , кажется, директива .CFI после каждой строки , а также есть широкий varities этих напр., .cfi_startproc, И .cfi_endprocт.д .. больше здесь .

    .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

Я не понял цели этого.

когти
источник
3
описание cfiинструкции GNU AS здесь
Пасхалис
related: Как убрать «шум» из вывода сборки GCC / clang? , если вам просто нужны инструкции без директив. Хороший способ - разместить свой код на gcc.godbolt.org, чтобы увидеть хороший отфильтрованный вывод asm из различных версий различных компиляторов (включая не x86) с выделением цвета, чтобы соответствовать исходным строкам с блоками asm.
Питер Кордес

Ответы:

70

У меня такое чувство, что это означает информацию о кадре вызова и является расширением GNU AS для управления кадрами вызова. Из DeveloperWorks :

На некоторых архитектурах обработкой исключений необходимо управлять с помощью директив Call Frame Information. Эти директивы используются в сборке для управления обработкой исключений. Эти директивы доступны в Linux на POWER, если по какой-либо причине (например, переносимость базы кода) информации об обработке исключений, созданной GCC, недостаточно.

Похоже, что они генерируются на некоторых платформах в зависимости от необходимости обработки исключений.

Если вы хотите отключить их, см . Ответ Дэвида .

Сообщество
источник
5
Также не могли бы вы сказать пару слов о .LFB0, .LFB1, .LFE0, .LFE1
claws
@claws - это метки, созданные компилятором (как видно из файла :). См. Stackoverflow.com/a/15285058/4294399
Calculuswhiz
144

Чтобы отключить их, используйте опцию gcc

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm может также понадобиться.

Дэвид Ватсон
источник
12
-fno-dwarf2-cfi-asmможет также понадобиться
technosaurus
Если вы отключаете его для удобочитаемого вывода asm, см. Как удалить «шум» из вывода сборки GCC / clang? для других полезных опций и хитростей.
Питер Кордес
30

Директивы CFI используются для отладки. Это позволяет отладчику раскручивать стек. Например: если процедура A вызывает процедуру B, которая затем вызывает общую процедуру C. Процедура C не выполняется. Теперь вы хотите знать, кто на самом деле звонил C, а затем вы можете узнать, кто звонил B.

Отладчик может раскрутить этот стек, используя указатель стека (% rsp) и зарегистрировав% rbp, однако он должен знать, как их найти. Вот где вступают в силу директивы CFI.

movq    %rsp, %rbp
.cfi_def_cfa_register 6

поэтому последняя строка здесь сообщает, что "Адрес кадра вызова" теперь находится в регистре 6 (% rbp)

Грэм Стотт
источник
2
Но, я думаю, использование cfi для обработки исключений должно быть более частым, чем отладка.
osgx 08
6
Фактически CFA означает «канонический адрес кадра». Смотрите здесь .
Кэмерон
1
Директивы CFI позволяют раскручивать стек даже для кода, скомпилированного с помощью -fomit-frame-pointer, в качестве альтернативы RBP (которая по умолчанию включена с gcc или clang -O1и выше). Он используется обработкой исключений C ++, а также отладчиками / профилировщиками. В коде с традиционными указателями кадров RBP текущее значение RBP всегда указывает на сохраненное значение RBP, а это указывает на предыдущее, формируя связанный список. В этом случае нет необходимости в CFI. (Хотя в функциях, которые используют указатель кадра, CFI cfa_register позволяет избежать необходимости в дополнительных метаданных для каждого изменения RSP, как вы показываете.)
Питер Кордес,
2

Чтобы отключить их, g ++ требуется -fno-exceptionsнаряду с ранее упомянутым -fno-asynchronous-unwind-tables, при условии, что вы не используете исключения.

iw4h
источник