在 Linux w/GCC 上删除 C 库
Dropping C library on Linux w/GCC
我正在尝试创建一个基本的应用程序,它只需要大量的原始系统调用,我不需要 C 库。我还试图将尺寸保持在绝对最小值。对于像 strcpy
、strcmp
这样的函数,我希望使用编译器内部函数。
在 Windows 和 MSVC/GCC 上,我可以使用 /NODEFAULTLIB
或 -nostdlib
从 C 标准库分离。然后我将简单地 link 到 kernel32.lib
、user32.lib
,以使用 WriteFile
、CreateWindowExW
等函数。我正在尝试在linux 但我 运行 遇到了一些问题。
似乎出于某种原因,系统调用的代码 read
、write
、ptrace,
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.c
和 ld 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
我正在尝试创建一个基本的应用程序,它只需要大量的原始系统调用,我不需要 C 库。我还试图将尺寸保持在绝对最小值。对于像 strcpy
、strcmp
这样的函数,我希望使用编译器内部函数。
在 Windows 和 MSVC/GCC 上,我可以使用 /NODEFAULTLIB
或 -nostdlib
从 C 标准库分离。然后我将简单地 link 到 kernel32.lib
、user32.lib
,以使用 WriteFile
、CreateWindowExW
等函数。我正在尝试在linux 但我 运行 遇到了一些问题。
似乎出于某种原因,系统调用的代码 read
、write
、ptrace,
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.c
和 ld 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