71

我想在没有 (g)libc 的情况下编译我的 C 代码。如何停用它以及哪些功能取决于它?

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

4

2 回答 2

86

如果你用 编译你的代码-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()不可用。

于 2010-03-30T20:48:09.170 回答
9

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

你会发现 gcc 生成的代码可能对一些隐藏的函数有一些依赖。他们中的大多数都在libgcc.a. memcpy()在 libc 中可能还有对、和的隐藏调用memmove(),因此您可能必须提供自己的版本(这并不难,至少只要您对性能不太挑剔)。memset()memcmp()

如果您查看生成的程序集(使用标志) ,有时事情可能会变得更清楚。-S

于 2010-03-30T20:44:45.920 回答