Bee*_*ope 6 x86 assembly linker 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
Run Code Online (Sandbox Code Playgroud)
...建造使用:
nasm -f elf64 label-test.s
ld label-test.o -o label-test
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
请注意,两者normal_label
和本地标签local_label
最终都在符号表中.所有这些都最终都在可执行文件的符号表中.
我不想将这些符号发送到最终的可执行文件.我可以告诉他们不要包含它们吗?我可以传递一些选项ld
,例如--strip-all
,将删除这些符号,但也删除可执行文件中的所有其他符号.这使得它成为了一个重点:它消除了我真正想要保留的符号,用于可读的堆栈跟踪,调试等.
正如Peter Cordes所提到的那样,FWIW yasm
没有完全相同的问题.使用.o
与上面完全相同的方式构建的elf64 文件(但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
Run Code Online (Sandbox Code Playgroud)
全局_start
标签仍然包含在内,但其他两个标签未命名 - 它们仍在那里,它们是偏移4和2的未命名符号(上面列表中的第2和第3行).这可以通过添加更多标签来确认 - 生成更多未编辑的符号.
据我所知,这只是 nasm 的一个限制。例如,请参阅此论坛帖子,其中的海报具有大致相同的问题(尽管是 32 位而不是 64 位 ELF),并且除了使用剥离工具之外没有提供任何解决方案。
就我而言,似乎剥离了目标文件,如:
strip --discard-all label-test.o
Run Code Online (Sandbox Code Playgroud)
应该做的伎俩。尽管有这个--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
Run Code Online (Sandbox Code Playgroud)
之后:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g .text 0000000000000000 _start
Run Code Online (Sandbox Code Playgroud)
特别要注意的是,.text
尽管它是本地的,但单独保留部分符号是足够聪明的。当然,这个 strip 选项不能真正区分无用(循环标签)和潜在有用的符号,例如使用各种工具提供正确堆栈跟踪所需的本地函数入口点。
如果您想更聪明一点,您可以.
使用--wildcard
和--strip-symbol
选项选择性地仅去除带有嵌入.
.
如果有人潜伏在那里,我仍在寻找更好的答案。