所有asm标签都成为可执行文件

时间:2016-09-23 05:29:59

标签: assembly linker x86 nasm elf

使用nasm组装对象时,我发现所有标签都包含在结果.o文件中的符号中,以及最终的二进制文件。

这对于我声明为GLOBAL的函数入口点以及对于部分开始部分(例如,对于.text部分)是有意义的,但标签仅仅用作循环入口点和这样的所有附近都出现在输出文件中。除了泄漏内部实现细节之外,它还浪费了符号表中的空间。

例如,鉴于这个简短的装配程序:

GLOBAL _start
_start:
    xor eax, eax
normal_label:
    xor eax, eax
.local_label:
    xor eax, eax
    xor edi, edi
    mov eax, 231    ;  exit(0)
    syscall

...使用:

构建
nasm -f elf64 label-test.s
ld label-test.o -o label-test

在对象文件和链接的可执行文件中生成l(即本地)符号:

objdump --syms label-test.o

label-test.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 label-test.s
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000002 l       .text  0000000000000000 normal_label
0000000000000004 l       .text  0000000000000000 normal_label.local_label
0000000000000000 g       .text  0000000000000000 _start

请注意,normal_label和本地标签local_label最终都出现在符号表中。所有这些都最终都在可执行文件的符号表中。

我不想将这些符号发送到最终的可执行文件。我可以告诉他们不要包含它们吗?我可以将一些选项传递给ld,例如--strip-all,这将删除这些符号,但也会删除可执行文件中的所有其他符号。这使得它成为了一个笨蛋:它消除了我真正想要保留的符号,用于可读的堆栈跟踪,调试等。

如彼得科德斯所提到的那样,FWIW yasm并没有完全相同的问题。使用与上面完全相同的方式构建的elf64 .o文件(但yasm代替nasm,我们得到:

objdump --syms label-test-yasm.o 

label-test-yasm.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 label-test.s
0000000000000004 l       .text  0000000000000000 
0000000000000002 l       .text  0000000000000000 
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 g       .text  0000000000000000 _start

仍然包含全局_start标签,但其他两个标签尚未命名 - 它们仍在那里,它们是偏移4和2处的未命名符号(第2和第3行)上面的列表)。这可以通过添加更多标签来确认 - 生成更多未经编辑的符号。

2 个答案:

答案 0 :(得分:3)

据我所知,这只是一个限制。例如,参见this forum post,其中海报具有大致相同的问题(尽管是32位而不是64位ELF),除了使用剥离工具之外,没有提供任何解决方案。

就我而言,它似乎剥离了对象文件,如:

strip --discard-all label-test.o 

应该做的伎俩。尽管--discard-all选项的名称,它只剥离局部符号并仅留下全局符号。在剥离文件之前,这是符号表:

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 label-test.s
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000002 l       .text  0000000000000000 normal_label
0000000000000004 l       .text  0000000000000000 normal_label.local_label
0000000000000000 g       .text  0000000000000000 _start

之后:

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 label-test.s
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 g       .text  0000000000000000 _start

请特别注意,仅仅保留.text部分符号就足够聪明,即使它是本地符号。当然,这个条带选项无法真正区分无用(循环标签)和可能有用的符号,例如使用各种工具提供正确堆栈跟踪所需的本地函数入口点。

如果您想更聪明一点,您可以选择性地使用.--wildcard选项仅删除asm-local(即以--strip-symbol开头的标签)仅剥离嵌入了.的标签。

如果有人潜伏在那里,我还在寻找更好的答案。

答案 1 :(得分:2)

有点晚了,但是我遇到了这个问题,并为nasm 2.15编写了一个补丁来解决此问题。它添加了一个名为“ -discard-labels”的命令行开关。您可以在这里获取它:https://forum.nasm.us/index.php?topic=2666.0