在 Linux w/GCC 上删除 C 库

Dropping C library on Linux w/GCC

我正在尝试创建一个基本的应用程序,它只需要大量的原始系统调用,我不需要 C 库。我还试图将尺寸保持在绝对最小值。对于像 strcpystrcmp 这样的函数,我希望使用编译器内部函数。

在 Windows 和 MSVC/GCC 上,我可以使用 /NODEFAULTLIB-nostdlib 从 C 标准库分离。然后我将简单地 link 到 kernel32.libuser32.lib,以使用 WriteFileCreateWindowExW 等函数。我正在尝试在linux 但我 运行 遇到了一些问题。

似乎出于某种原因,系统调用的代码 readwriteptrace, process_vm_readv 等实际上都在 gclib 中?我尝试使用 syscall(SYS_write, ...) 以及我希望它能以某种方式内联到我的程序中,但它仍然需要 gclib。有没有办法像在 Windows 上那样调用这些系统调用,我会在其中 link 调用系统库而不是 C 库?我想避免使用内联 ASM 自己编写系统调用存根。我开始像这样使用 linux 编程,所以我不太确定。这是我正在使用的一个简单的测试应用程序(未编译):

#include <unistd.h>

void ProcessEntry()
{
    write(STDOUT_FILENO, "Detached from CRT", 18);
    _exit(0);
}

我正在使用命令:gcc -c program.cld program.o -nostdlib -e ProcessEntry

这是我得到的:

#include <sys/syscall.h>

// Copied from MUSL libc
// There are more at
// http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/syscall_arch.h
static __inline long __syscall1(long n, long a1) {
  unsigned long ret;
  __asm__ __volatile__("syscall"
                       : "=a"(ret)
                       : "a"(n), "D"(a1)
                       : "rcx", "r11", "memory");
  return ret;
}

void do_exit(int status) { __syscall1(SYS_exit, status); }

void entry() { do_exit(5); }

另存为syscall.c并用

编译
cc -Wall -W -pedantic -static -O3 -march=native -flto -fno-fat-lto-objects  -fPIC -fPIE -fstack-protector-strong -std=gnu18 -nostdlib -e entry  syscall.c   -o syscall

这是 9,224 字节程序的整个反汇编:

0000000000001000 <entry>:
    1000:   f3 0f 1e fa             endbr64
    1004:   b8 3c 00 00 00          mov    [=12=]x3c,%eax
    1009:   bf 05 00 00 00          mov    [=12=]x5,%edi
    100e:   0f 05                   syscall
    1010:   c3                      retq