Что такое .LFB.LBB.LBE.LVL.loc в компиляторе сгенерированный код сборки

Когда я просматриваю код сборки, сгенерированный GCC, существует много строк, начинающихся с .LBB и числа. Кажется, что они не являются инструкциями операций. Больше похоже на маркировку чего-либо файла или что-то.

Что такое .LFB,. LVL, LBB, LBE и т.д. находятся в коде сборки, сгенерированном компилятором? ".loc" означает "строка кода". Указывают ли эти строки только symbol table?

Вот фрагмент кода,

main:
.LFB1:
  .loc 1 8 0
  .cfi_startproc
.LVL2:
.LBB4:
.LBB5:
  .loc 1 2 0
  movsd b(%rip), %xmm0
.LBE5:
.LBE4:
  .loc 1 10 0
  xorl  %eax, %eax
.LBB7:
.LBB6:
  .loc 1 2 0
  mulsd a(%rip), %xmm0
.LBE6:
.LBE7:
  .loc 1 9 0
  movsd %xmm0, a(%rip)
.LVL3:
  .loc 1 10 0
  ret
  .cfi_endproc

Ответ 1

.loc

Как упоминалось Ferruccio .loc, это директива отладки, и она появляется только в GCC 4.8.2, если вы сообщите компилятору генерировать отладочную информацию с помощью -ggdb.

.loc документируется на https://sourceware.org/binutils/docs-2.18/as/LNS-directives.html#LNS-directives, а точный результат зависит от формата данных отладки (DWARF2 и т.д.).

Другими являются метки.

.L префикс

GCC использует .L для локальных меток.

GAS не будет генерировать какие-либо символы на скомпилированном выходе по умолчанию, как описано в: https://sourceware.org/binutils/docs-2.18/as/Symbol-Names.html

Локальный символ - это любой символ, начинающийся с определенных префиксов локальных меток. По умолчанию префикс локальной метки - `.L 'для систем ELF

Локальные символы определяются и используются внутри ассемблера, но обычно они не сохраняются в объектных файлах. Таким образом, они не видны при отладке. Вы можете использовать опцию -L (см. "Включение локальных символов: -L" ), чтобы сохранить локальные символы в объектных файлах.

Итак, если вы скомпилируете с помощью: as -c a.S, nm a.o не отображает эти метки вообще.

Это имеет смысл только потому, что вы не можете генерировать такие метки из программы C.

Есть также опции, которые управляют им, как:

  • man as --keep-locals
  • man ld --discard-all

Это, по-видимому, является специальным соглашением по связям с GCC, а не частью ELF ABI или NASM.

Кроме того, как NASM, так и GAS используют соглашение, в котором метки, начинающиеся с периода (но не .L в GAS), генерируют локальные символы: http://www.nasm.us/doc/nasmdoc3.html#section-3.9 все еще присутствуют на выходе.

Суффиксы

Суффиксы, о которых вы упоминаете, как представляется, связаны с отладкой, поскольку они определены в gcc/dwarf2out.c в GCC 4.8.2 и DWARF2 является основным форматом информации для отладки для ELF:

#define FUNC_BEGIN_LABEL  "LFB"
#define FUNC_END_LABEL    "LFE"
#define BLOCK_BEGIN_LABEL "LBB"
#define BLOCK_END_LABEL   "LBE"
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);

Из моих экспериментов некоторые из них генерируются только с помощью gcc -g, другие даже без g.

Как только у нас есть эти имена определений, легко сгенерировать C-код, который генерирует их, чтобы увидеть, что они означают:

  • LFB и LFE создаются в начале и в конце функций

  • LBB и LBE были сгенерированы следующим кодом с gcc -g во внутренних областях функциональных блоков:

    #include <stdio.h>
    
    int main() {
        int i = 0;
        {
            int i = 1;
            printf("%d\n", i);
        }
        return 0;
    }
    
  • LVL: TODO Я не мог легко понять это. Нам нужно будет интерпретировать источник еще немного.

Ответ 2

Директива .loc используется для указания соответствующей строки исходного кода. Он указывает номер файла, номер строки и номер столбца соответствующего исходного кода.

Остальные выглядят как ярлыки.