我有两个C源文件
foo1.c:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
puts("hello world");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并且foo2.c:
#include <stdlib.h>
#include <stdio.h>
void _start(void)
{
puts("hello world");
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
我在我的i386 GNU/Linux平台上编译它们:
$ #compile foo1
$ cc -o foo1 foo1.c
$ #compile foo2
$ cc -S foo2.c
$ as -o foo2.o foo2.s
$ ld -o foo2 -dynamic-linker /lib/i386-linux-gnu/ld-linux.so.2 -lc foo2.o
$ #notice that crt1.o and others are missing
Run Code Online (Sandbox Code Playgroud)
从用户的角度来看,输出的可执行文件做同样的事情.
$ ./foo1
hello world
$ ./foo2
hello world
Run Code Online (Sandbox Code Playgroud)
但他们是不同的:
$ wc -c foo1
5000
$ wc -c foo2
2208
$ objdump -d foo1 | wc -l
238
$ objdump -d foo2 | wc -l
35
Run Code Online (Sandbox Code Playgroud)
即使我启用gcc的-Os选项来优化大小,
$ #compile foo1
$ gcc -o foo1 foo1.c -Os
Run Code Online (Sandbox Code Playgroud)
它不小:
$ wc -c foo1
4908
$ objdump -d foo1 | wc -l
229
Run Code Online (Sandbox Code Playgroud)
是否有任何方法可以让GCC优化crt1.o我怀疑对这个臃肿的文件大小有用的部分和朋友而不诉诸非标准代码和奇怪的(在某些情况下可能有害)编译?我的GCC的版本字符串是" gcc (Debian 4.9.2-10) 4.9.2".
使用gcc/clang -nostartfiles,但您使用的c库可能依赖于它自己_start()的动态链接实现.由于您使用的是Linux,我建议使用静态构建的musl-libc.
或者,您可以实现write()和系统exit()调用并将'\n'添加到字符串中以通过使用_start()而不是使用来完全避免使用c库main().如果需要访问argc,argv和envp,则需要一些内联汇编来访问堆栈(无论架构如何,Linux都会在堆栈中传递所有ELF二进制文件).