2010-03-30 136 views
42

我想编译我的C代码而没有(g)libc。我如何禁用它以及哪些功能依赖于它?没有libc编译

我试过-nostdlib,但它没有帮助:代码是可编译的并且运行,但我仍然可以在我的可执行文件的hexdump中找到libc的名称。

+1

'-nostdlib'应该这样做,您使用什么平台/编译器版本? – 2010-03-30 20:36:23

+0

“没有帮助”,因为在那里没有禁用库,或者你不能用该标志编译任何东西? – 2010-03-30 20:47:28

+3

你可能也想要-nostartupfiles。 – 2010-03-30 22:03:23

回答

53

如果你用-nostdlib编译你的代码,你将无法调用任何C库函数(当然),但你也不会得到常规的C引导代码。特别是,Linux上程序的真正入口点不是main(),而是一个名为_start()的函数。标准库通常提供一个运行一些初始化代码的版本,然后调用main()。

尝试用gcc编译-nostdlib此:

void _start() { 

    /* main body of program: call main(), etc */ 

    /* exit system call */ 
    asm("movl $1,%eax;" 
     "xorl %ebx,%ebx;" 
     "int $0x80" 
    ); 
} 

的_start()函数应始终以一个呼叫结束退出(或其他非返回系统调用如exec)。上面的示例直接调用了内联汇编的系统调用,因为通常的exit()不可用。

+3

对于64位,汇编代码如下所示:'asm(“mov rax,60; mov rdi,0; syscall”)'。 – sigalor 2016-05-03 18:03:27

+3

添加到@ sigalor的评论中,要用'gcc'编译,你需要使用AT&T语法,所以它应该如下所示:'asm(mov $ 60,%rax; mov $ 0,%rdi; syscall)' – lanoxx 2016-05-11 11:59:22

+0

@ataylor:为什么_start()函数应该总是以调用exit()结束?如果我不在start()函数中写入exit()会怎么样? – Destructor 2017-05-25 05:52:27

6

将C代码编译为目标文件(gcc -c以获得*.o文件)并将其直接链接到链接器(ld)的最简单方法。您必须将目标文件与一些额外的目标文件(如/usr/lib/crt1.o)链接起来,才能获得可执行的可执行文件(在内核看到的入口点和main()函数之间,有一些工作要做) 。要知道要链接什么,请尝试使用gcc -v与glibc链接:这应该显示通常进入可执行文件的内容。

你会发现gcc生成的代码可能对一些隐藏的函数有一些依赖关系。他们大多数在libgcc.a。可能还有隐藏的电话memcpy()memmove()memset()memcmp(),它们位于libc中,因此您可能需要提供自己的版本(这并不困难,至少只要您对性能不太挑剔)。

东西可能如果您查看生产的组件(使用-S标志),有时会更清晰。

+0

我必须使用_start而不是main,但是当我尝试调用libc函数时,gcc不会发出抱怨。如果我删除所有libc-calls,libc-link会消失吗? – dkreuter 2010-04-01 07:50:51

+2

不是直接。如果你尝试'gcc -v',你会看到'gcc'给连接器('* .o')提供了一些目标文件。链接器包含所有的对象文件。 “消失”只发生在图书馆('*。a'),因为它们是链接器可以使用或不使用的对象文件的存储库。 – 2010-04-01 13:37:16