在编译器生成的汇编代码中,什么是.LFB .LBB .LBE .LVL .loc

问题描述 投票:16回答:2

[当我查看由GCC生成的汇编代码时,有很多以.LBB开头的行和一个数字。看来它们不是操作指令。更像标记文件的内容或内容。

在编译器生成的汇编代码中,.LFB,。LVLLBBLBE等是什么?.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
c gcc assembly
2个回答
17
投票

。loc

正如Ferruccio .loc所提到的,它是一个调试指令,只有当您告诉编译器使用-ggdb生成调试信息时,它才会出现在GCC 4.8.2中。

.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中所述

本地符号是任何以某些本地标签前缀开头的符号。默认情况下,ELF系统的本地标签前缀为`.L'

本地符号是在汇编器中定义和使用的,但是它们通常不保存在目标文件中。因此,它们在调试时不可见。您可以使用-L选项(请参见包括本地符号:-L)将本地符号保留在目标文件中。

因此,如果您使用:as -c a.S进行编译,nm a.o根本不会显示这些标签。

这仅是有意义的,因为您不能从C程序生成此类标签。

也有一些类似的选项来管理它:

  • [man as--keep-locals
  • [man ld--discard-all
  • 这似乎是GCC工具链的特定约定,不属于ELF ABI或NASM。

此外,NASM和GAS都使用以句点开头的标签(但GAS中不是.L的标签会生成局部符号:http://www.nasm.us/doc/nasmdoc3.html#section-3.9但仍存在于输出中的约定。

后缀

您提到的所有后缀似乎都与调试相关,因为它们均在GCC 4.8.2的gcc/dwarf2out.c下定义,并且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代码,以了解它们的含义:

  • [LFBLFE在函数的开头和结尾处生成

  • [LBBLBE是通过以下代码在内部功能块范围内使用gcc -g生成的:

#include <stdio.h>

int main() {
    int i = 0;
    {
        int i = 1;
        printf("%d\n", i);
    }
    return 0;
}
  • LVL:TODO我无法轻松理解它。我们需要对源代码进行更多解释。


  • 3
    投票

    .loc伪指令用于指示源代码的相应行。它指示相应源代码的文件号,行号和列号。

    © www.soinside.com 2019 - 2024. All rights reserved.