【问题标题】:All asm labels becoming symbols in executable file所有 asm 标签成为可执行文件中的符号
【发布时间】:2017-01-31 20:49:39
【问题描述】:

使用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 都以符号表结尾。它们也都在可执行文件的符号表中。

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


FWIW,正如 Peter Cordes 所说,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 行)。这可以通过添加更多标签来确认 - 会产生更多未命名的符号。

【问题讨论】:

  • yasm 默认不这样做。 (如果你使用-gdwarf2,它会这样做)
  • 嗯,是的。所以也许这有点怪癖。我将其添加到问题的底部。您提到了-g 的东西,我想到这些是为调试添加的主要内容,但值得注意的是ld 命令上的--strip-debug 不会删除nasm 构建的二进制文件中的那些(或任何符号)。
  • 好吧,这次我用谷歌搜索得更厉害了,似乎它可能只是一个limitation in nasm
  • 对,我的意思是我假设有某种方法可以摆脱 . 标签,留下非. 标签。即,我认为 nasm 会有某种方式来完成 yasm 的工作(因为它显然很有用),但由于我通常只使用 yasm,所以没有费心去看。
  • 对 yasm 的更正,它确实将条目添加到符号表中,但它们是“未命名的”。上面添加了详细信息。

标签: assembly linker x86 nasm elf


【解决方案1】:

据我所知,这只是 nasm 的一个限制。例如,请参阅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 部分符号单独保留是足够聪明的,即使它是本地的。当然,这个 strip 选项并不能真正区分无用(循环标签)和可能有用的符号,例如使用各种工具提供正确堆栈跟踪所需的本地函数入口点。

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 谢谢!我对你在那篇文章中提到的在 Linux 上完成的 nasm-DWARF 工作很感兴趣。我可以在哪里阅读更多相关信息?
    • 嗨,BeeOnRope,我有一个 BASIC 编译器,我正在这里工作:github.com/clockworkdevstudio/idlewild-lang。但它真的是实验性的,甚至不是 alpha。目前甚至只有 Linux 版本会构建。所有 DWARF 的东西都位于三个不同的文件中,Compiler.hs、Semantics.hs 和 DWARF.hs。
    猜你喜欢
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多