如何避免C运行时(crt * .o)垃圾

时间:2016-08-09 21:02:45

标签: c gcc crt

我有两个C源文件

foo1.c

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    puts("hello world");
    return 0;
}

foo2.c

#include <stdlib.h>
#include <stdio.h>

void _start(void)
{
    puts("hello world");
    exit(0);
}

我在我的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

从用户的角度来看,输出的可执行文件也是一样的。

$ ./foo1
hello world
$ ./foo2
hello world

但他们是不同的:

$ wc -c foo1
5000
$ wc -c foo2
2208
$ objdump -d foo1 | wc -l
238
$ objdump -d foo2 | wc -l
35

即使我启用了gcc的-Os选项来优化尺寸,

也是如此
$ #compile foo1
$ gcc -o foo1 foo1.c -Os

它不小:

$ wc -c foo1
4908
$ objdump -d foo1 | wc -l
229

有没有办法让GCC优化crt1.o和朋友的部分,我怀疑这些膨胀的文件大小有助于不使用非标准代码和奇怪的(在某些情况下可能有害)编译?我的GCC版本字符串是“gcc (Debian 4.9.2-10) 4.9.2”。

1 个答案:

答案 0 :(得分:7)

使用gcc / clang,您可以使用-nostartfiles,但您使用的c库可能依赖于自己的_start()动态链接实现。由于您使用的是Linux,我建议使用静态构建的musl-libc。

或者,您可以实施write()exit()系统调用,然后添加&#39; \ n&#39;使用_start()代替main()来完全避免使用c库。如果需要访问argc,argv和envp,则需要一些内联汇编来访问堆栈(无论架构如何,Linux都会在堆栈中传递所有ELF二进制文件。)