为什么链接器不会从可执行文件中删除主例程

时间:2016-09-18 13:11:58

标签: linker main

我测试了两个成功退出最小程序,第一个使用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 的程序规模较大。 为什么链接器不会从二进制文件中删除 main 例程来优化大小?我的意思是在编译C程序后得到目标文件的链接器。

1 个答案:

答案 0 :(得分:1)

  

为什么链接器不会从可执行文件中删除主例程?

因为链接器通常不会从给定的对象文件中删除任何例程。他们根本就不在那个行业。

链接器不在例程上运行,它们在部分上运行。一些链接器可以有限地删除未引用的部分,例如GNU BFD ld和Gold有--gc-sections标志,但在你的例子中没有未引用的部分,所以无论如何都没有GC。

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

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

  

这是argc / argv建立过程,占用几千字节?

如果您正在使用GNU ld,您可以要求链接器告诉您完全使用链接器--print-map参数占用多少空间。

在ELF平台上,您还可以使用nm main查看哪些符号占用最终二进制文件中的空格,并使用ld -y <symbol> ...查看这些符号的链接位置。