为什么链接器不从可执行文件中剥离主例程?
why linker does not strip main routine from executable?
我测试了两个成功退出的小程序,第一个使用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 程序编译后获取目标文件的链接器。
why linker does not strip main routine from executable?
因为链接器通常不会从给定的目标文件中删除 任何 例程。他们根本不在那个行业。
链接器不对例程进行操作,它们对节进行操作。一些链接器可以有限地删除 unreferenced 部分,例如GNU BFD ld 和 Gold 有 --gc-sections
标志,但在您的示例中没有未引用的部分,因此无论如何都不会进行 GC。
现在,您的两个程序之间的区别在于,在 C 运行时启动时带有 main
链接的程序(通常为 crt0.o
),并设置 argc
和 argv
参数 main
被定义为期望它们的方式。
您的 main
不关心这个,但需要一个非常聪明的链接器才能推断出这一点。此外,您的 main
确实 关心返回后调用 sys_exit
,因此它实际上需要 crt0.o
才能正常关闭。
Is is that argc/argv setting-up process, that takes up few kilobytes?
如果您使用的是 GNU ld,您可以要求链接器 确切地告诉您 什么使用了多少 space 以及链接器 --print-map
参数。
在 ELF 平台上,您还可以使用 nm main
查看最终二进制文件中哪些符号占用 space,并使用 ld -y <symbol> ...
查看这些符号在哪里链接来自.
我测试了两个成功退出的小程序,第一个使用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 程序编译后获取目标文件的链接器。
why linker does not strip main routine from executable?
因为链接器通常不会从给定的目标文件中删除 任何 例程。他们根本不在那个行业。
链接器不对例程进行操作,它们对节进行操作。一些链接器可以有限地删除 unreferenced 部分,例如GNU BFD ld 和 Gold 有 --gc-sections
标志,但在您的示例中没有未引用的部分,因此无论如何都不会进行 GC。
现在,您的两个程序之间的区别在于,在 C 运行时启动时带有 main
链接的程序(通常为 crt0.o
),并设置 argc
和 argv
参数 main
被定义为期望它们的方式。
您的 main
不关心这个,但需要一个非常聪明的链接器才能推断出这一点。此外,您的 main
确实 关心返回后调用 sys_exit
,因此它实际上需要 crt0.o
才能正常关闭。
Is is that argc/argv setting-up process, that takes up few kilobytes?
如果您使用的是 GNU ld,您可以要求链接器 确切地告诉您 什么使用了多少 space 以及链接器 --print-map
参数。
在 ELF 平台上,您还可以使用 nm main
查看最终二进制文件中哪些符号占用 space,并使用 ld -y <symbol> ...
查看这些符号在哪里链接来自.