我想在没有(g)libc的情况下编译我的C代码。如何停用它以及哪些功能依赖于它?
我尝试了-nostdlib,但它没有帮助:代码可编译并运行,但我仍然可以在我的可执行文件的hexdump中找到libc的名称。
答案 0 :(得分:65)
如果使用-nostdlib
编译代码,则无法调用任何C库函数(当然),但您也无法获得常规C引导代码。特别是,Linux上程序的真正入口点不是main()
,而是一个名为_start()
的函数。标准库通常提供运行一些初始化代码的版本,然后调用main()
。
尝试使用gcc -nostdlib -m32
:
void _start() {
/* main body of program: call main(), etc */
/* exit system call */
asm("movl $1,%eax;"
"xorl %ebx,%ebx;"
"int $0x80"
);
}
_start()
函数应始终以调用exit
(或其他非返回系统调用,如exec
)结束。上面的示例直接使用内联汇编调用系统调用,因为通常的exit()
不可用。
答案 1 :(得分:6)
最简单的方法是将C代码编译为目标文件(gcc -c
以获取一些*.o
文件),然后将它们直接链接到链接器(ld
)。您必须将目标文件与一些额外的目标文件(例如/usr/lib/crt1.o
)链接起来才能获得可用的可执行文件(在内核看到的入口点和main()
函数之间)有点工作要做)。要知道要链接的内容,请尝试使用gcc -v
与glibc链接:这应该会显示通常可执行文件中的内容。
你会发现gcc生成的代码可能与一些隐藏的函数有一些依赖关系。他们中的大多数都在libgcc.a
。对于{lib}中的memcpy()
,memmove()
,memset()
和memcmp()
,可能还会隐藏调用,因此您可能需要提供自己的版本(不是很难,至少只要你对表现不太挑剔就可以了。)
如果您查看生成的程序集(使用-S
标志),可能有时会更清晰。