为什么链接器不从可执行文件中剥离主例程



我测试了两个成功退出的最小程序,第一个使用libc,第二个不使用libc

:

    segment .text
    global main
main:
    xor eax, eax
    ret

构建和检查大小:

yasm -f elf64 main.s; clang -o main main.o; stat ./main
...
Size: 8552
...
第二:

    segment .text
    global _start
_start:
    mov eax, 60
    xor edi, edi
    syscall

构建和检查大小:

yasm -f elf64 main.s; ld -o main main.o; stat ./main
...
Size: 704
---

显然,使用main的程序体积更大。为什么链接器不从二进制文件中剥离例程来优化大小?我指的是在C程序编译后获取目标文件的链接器。

为什么链接器不从可执行文件中剥离主例程?

因为链接器一般不会从给定的目标文件中剥离任何例程。他们根本不在那一行。

链接器不操作例程,它们操作。一些链接器可以有限地删除未引用的部分,例如GNU BFD ld和Gold有--gc-sections标志,但在您的示例中没有未引用的部分,因此无论如何都不会被GC。

现在,您的两个程序之间的区别在于,main链接在C运行时启动(通常是crt0.o),并设置argcargv参数的方式main被定义为期望它们。

你的main不关心这个,但它需要一个非常聪明的链接器来推断。此外,您的main 确实关心返回后调用sys_exit,因此它实际上需要crt0.o才能正常关闭。

是argc/argv设置过程,占用了几千字节吗?

如果你使用的是GNU ld,你可以要求链接器告诉你确切的是什么使用了多少空间与链接器--print-map参数。

在ELF平台上,您还可以使用nm main来查看哪些符号在最终二进制文件中占用了空间,并使用ld -y <symbol> ...来查看这些符号从哪里得到链接。

相关内容

  • 没有找到相关文章

最新更新