没有libc编译

u14*_*796 53 c gcc glibc libc demo

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

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

ata*_*lor 68

如果使用-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"
    );
}
Run Code Online (Sandbox Code Playgroud)

_start()函数应始终以对exit(或其他非返回系统调用,如exec)的调用结束.上面的示例直接使用内联汇编调用系统调用,因为通常的exit()不可用.

  • 添加@sigalor的注释,用`gcc`编译你需要使用AT&T语法,所以这应该如下所示:`asm(mov $ 60,%rax; mov $ 0,%rdi; syscall)` (5认同)
  • 对于64位,汇编代码必须如下所示:`asm("mov rax,60; mov rdi,0; syscall")`. (4认同)
  • @Destructor 在我的系统上挂起几秒钟,然后出现段错误。 (3认同)
  • @ataylor:为什么 _start() 函数应该总是以调用 exit() 结束?如果我不在 start() 函数中写 exit() 怎么办? (2认同)
  • 请注意,堆栈在“_start”入口处的对齐方式不同:堆栈上没有返回地址,因此它仍然是 16 字节对齐的。但GCC会假设它是一个普通函数,因此在调用其他函数时会违反ABI。对该文件使用 `-mincoming-stack-boundary=2` 来告诉 GCC 堆栈可能只有 4 - 在函数入口处对齐字节,或者可能是在 `_start` 上的 `__attribute__((target("something")))` (2认同)

Tho*_*nin 7

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

你会发现gcc生成的代码可能与一些隐藏的函数有一些依赖关系.他们中的大多数都在libgcc.a.另外,也可以隐藏的号召性memcpy(),memmove(),memset()memcmp(),这是在libc中,所以你可能必须提供自己的版本(这并不难,只要你不是太挑剔的性能至少).

如果你看一下生产的组件(使用标志),事情可能会更清楚-S.

  • 不是直接的.如果你尝试`gcc -v`,你会看到`gcc`给链接器提供了一些目标文件(`*.o`).链接器包括它给出的所有目标文件."消失"仅发生在库(`*.a`)中,因为它们是链接器可以自由使用或不使用的目标文件的存储库. (3认同)