linux - 使用 Linux 头文件中的 unistd.h 构建不带 libc 的静态 ELF

标签 linux gcc posix elf libc

我有兴趣使用 Linux 头文件提供的 unistd.h 构建一个没有 (g)libc 的静态 ELF 程序。

我已经阅读了这些文章/问题,这些文章/问题大致了解了我正在尝试做的事情,但并不完全是: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

Compiling without libc

https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free

我有只依赖于 unistd.h 的基本代码,其中,我的理解是这些函数中的每一个都是由内核提供的,不需要 libc。这是我选择的最有前途的方法:

    $ gcc -I /usr/include/asm/ -nostdlib grabbytes.c -o grabbytesstatic
    /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400144
    /tmp/ccn1mSkn.o: In function `main':
    grabbytes.c:(.text+0x38): undefined reference to `open'
    grabbytes.c:(.text+0x64): undefined reference to `lseek'
    grabbytes.c:(.text+0x8f): undefined reference to `lseek'
    grabbytes.c:(.text+0xaa): undefined reference to `read'
    grabbytes.c:(.text+0xc5): undefined reference to `write'
    grabbytes.c:(.text+0xe0): undefined reference to `read'
    collect2: error: ld returned 1 exit status

在此之前,我必须根据内核头文件中的值手动定义 SEEK_END 和 SEEK_SET。否则它会错误地说那些没有定义,这是有道理的。

我想我需要链接到一个未剥离的 vmlinux 以提供要使用的符号。然而,我通读了这些符号,虽然有很多 llseeks,但它们并不是逐字逐句的 llseeks。

所以我的问题可以朝几个方向发展:

如何指定一个 ELF 文件来使用来自的符号?我猜这是否可能/如何可能,符号将不匹配。如果这是正确的,是否有一个现有的头文件将重新定义 llseek 和 default_llseek 或内核中的任何内容?

有没有更好的方法在没有 libc 的情况下用 C 编写 Posix 代码?

我的目标是使用(可能只是)unistd.h 编写或移植相当标准的 C 代码,并在没有 libc 的情况下调用它。如果没有一些 unistd 函数,我可能还可以,并且不确定哪些函数“纯粹”存在于内核调用中。我喜欢组装,但这不是我的目标。希望尽可能保持严格的 C(如果必须的话,我可以使用一些外部汇编文件),以便在某些时候允许使用无 libc 的静态系统。

感谢阅读!

最佳答案

如果您打算用 C 语言编写 POSIX 代码,那么放弃 libc 不会有任何帮助。尽管您可以在汇编器中实现一个系统调用 函数,并从内核头文件中复制结构和定义,但您实际上是在编写自己的 libc,这几乎肯定不符合 POSIX 标准。有了所有出色的 libc 实现,几乎没有理由开始实现您自己的。

dietlibcmusl libc都是节俭的 libc 实现,它们产生非常小的二进制文件链接器通常很聪明;只要编写一个库来避免意外引入大量依赖项,实际上只有您使用的函数会链接到您的程序中。

这是一个简单的 hello world 程序:

#include<unistd.h>

int main(){
    char str[] = "Hello, World!\n";
    write(1, str, sizeof str - 1);
    return 0;
}

用下面的 musl 编译它会得到一个小于 3K 的二进制文件

$ musl-gcc -Os -static hello.c
$ strip a.out 
$ wc -c a.out
2800 a.out

dietlibc 生成一个更小的二进制文件,小于 1.5K:

$ diet -Os gcc hello.c
$ strip a.out 
$ wc -c a.out
1360 a.out

关于linux - 使用 Linux 头文件中的 unistd.h 构建不带 libc 的静态 ELF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14407832/

相关文章:

linux - 如何使用代理和 STUN 服务器设置 Asterisk SIP 注册?

linux - 如何编写具有 DOM 访问权限的简单浏览器?

c - 如何将编译选项从目标传播到 Cmake 上的所有其他目标

c++ - 无法编译,错误 : cryptlib. h:没有那个文件或目录

c - 厕所 key 示例中二进制信号量和互斥量之间的区别?

php - 为什么我不能将此键设置到 $_SESSION 中?

c - 下面给出的代码是错误的吗?

c++ - 在多线程环境中什么会导致 "bad file descriptor"?

linux - 内核模式 clock_gettime()

linux - 启动-停止-重启 shell 脚本的功能