我想在没有 (g)libc 的情况下编译我的 C 代码。如何停用它以及哪些功能取决于它?
我试过 -nostdlib 但它没有帮助:代码可编译并运行,但我仍然可以在可执行文件的 hexdump 中找到 libc 的名称。
如果你用 编译你的代码-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()
不可用。
最简单的方法是将 C 代码编译为目标文件(gcc -c
以获取一些*.o
文件),然后使用链接器( )直接链接它们ld
。您必须将您的目标文件与一些额外的目标文件链接起来,例如/usr/lib/crt1.o
为了获得一个可以工作的可执行文件(在内核所见的入口点和main()
函数之间,还有一些工作要做)。要知道要链接什么,请尝试与 glibc 链接,使用gcc -v
: 这应该向您展示通常进入可执行文件的内容。
你会发现 gcc 生成的代码可能对一些隐藏的函数有一些依赖。他们中的大多数都在libgcc.a
. memcpy()
在 libc 中可能还有对、和的隐藏调用memmove()
,因此您可能必须提供自己的版本(这并不难,至少只要您对性能不太挑剔)。memset()
memcmp()
如果您查看生成的程序集(使用标志) ,有时事情可能会变得更清楚。-S