fuz*_*fuz 8 linux system-calls systems-programming
最近的Linux内核(至少在amd64上)提供了一个魔术对象文件linux-vdso.so.1,该文件将syscall接口抽象到内核,允许内核选择最佳的调用约定.如果用C编写代码,glibc会自动使用该对象.
现在,如果我想在不使用glibc的情况下编写程序,我该如何使用这个对象?它提供的界面是否记录在某处?召唤大会怎么样?
这取决于您的实现是否为低级实用程序使用C接口.
如果您的语言工具直接访问系统调用而不通过C包装器,则您不需要使用VDSO(例如,您可以生成适当的SYSENTER机器指令来执行系统调用),但您可以决定使用VDSO然后利用它的.在这种情况下,您的语言甚至不需要遵循所有ABI约定,只需遵循内核的约定.(例如,您不需要ABI在寄存器上提供调用者安全的calle-safe区分,您甚至可以避免使用任何堆栈).
甚至不使用语言实现的一个例子libc.so是Bones Scheme.你可以找到其他几个.
我对VDSO的理解是它是一个抽象,由内核提供,在各个x86处理器系列之间抽象实现系统调用的各种小差异(与用户域 - >内核转换相关).如果您选择了特定的处理器目标,则不需要VDSO,您可以随时避免使用它.
AFAIU,VDSO是一个ELF共享对象,位于该段中(在我的Debian/AMD64上,最近编译的3.8.3内核)ffffffffff600000-ffffffffff601000; 准确地检查cat /proc/self/maps它在哪里).因此,您只需要了解ELF共享对象的组织并从中检索符号.看到这个和那个链接.VDSO使用C约定来调用x86-64 ABI规范中记录的调用.
也就是说,如果从进程空间中提取VDSO并将其写入磁盘文件,则结果是格式良好的ELF共享对象
ELF是一种记录良好的格式.x86-64 ABI约定也是如此
(它精确定义了C调用约定,以及进程'图像的确切开始.另请参见execve(2))手册页,当然还有内核文档,所以我不明白你的问题是什么?我同意理解ELF需要时间(我10年前做过,但我的记忆生疏).另请阅读<elf.h>计算机上的头文件.
例如; 运行(zsh64位Debian x86-64下)
% file $(which sash)
/bin/sash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
statically linked, for GNU/Linux 2.6.26,
BuildID[sha1]=0x0347fcc08fba2f811f58af99f26111d0f579a9f6, stripped
% ldd $(which sash)
not a dynamic executable
% sash
Stand-alone shell (version 3.7)
> ps |grep sash
21635 pts/3 00:00:00 sash
> cat /proc/21635/maps
00400000-004da000 r-xp 00000000 08:01 4985590 /bin/sash
006da000-006dc000 rw-p 000da000 08:01 4985590 /bin/sash
006dc000-006e1000 rw-p 00000000 00:00 0
017e3000-01806000 rw-p 00000000 00:00 0 [heap]
7fe4950e5000-7fe4950e7000 rw-p 00000000 00:00 0
7fff3f130000-7fff3f151000 rw-p 00000000 00:00 0 [stack]
7fff3f173000-7fff3f175000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Run Code Online (Sandbox Code Playgroud)
另见这个答案.
您可能希望在运行时内部使用能够简单地解析VDSO的动态链接器的最小版本.你当然想要了解一个过程开始的确切状态,特别auxv是辅助向量的作用(我真的忘记了这些细节,但我记得它们很重要).参见例如本文
实际上,可靠地启动运行时可能比VDSO问题更难.
您可能还想阅读linux程序集howto,它也解释了一些内容(但更多关于x86而不是x86-64)
顺便说一下,http://musl-libc.org/(这是一个替代的libc)的代码更容易阅读和理解(你将很容易地学习它们如何进行动态链接,pthreads等.)
我发现 Linux 内核树中的这些文件很有帮助:
Documentation/ABI/stable/vdso(vDSO 对象是什么?)Documentation/vDSO/parse_vdso.c(vDSO 对象的参考解析器)vDSO对象是一个虚拟的动态共享对象,总是映射到linux下的amd64进程的地址空间中。它可以用来实现快速的系统调用。要访问 vDSO 对象内部的函数,您需要
这两件事都可以通过CC0许可的参考实现parse_vdso.c来完成。