最近的Linux内核(至少在amd64上)提供了一个名为linux-vdso.so.1
的魔术对象文件,它将syscall接口抽象到内核,允许内核选择最佳的调用约定。如果用C编写代码,glibc会自动使用该对象。
现在,如果我想在不使用glibc的情况下编写程序,我该如何使用这个对象?它提供的界面是否记录在某处?召唤惯例怎么样?
答案 0 :(得分:8)
这取决于您的实现是否使用 C 接口来实现低级实用程序。
如果您的语言工具直接访问系统调用而不通过 C 包装器,则不需要使用VDSO(例如,您可以生成相应的SYSENTER
机器指令来执行系统调用),但您可以决定使用VDSO然后利用它。在这种情况下,您的语言甚至不需要遵循所有ABI约定,只需遵循内核的约定。 (例如,您不需要ABI在寄存器上提供调用者安全的calle-safe区分,甚至可以避免使用任何堆栈。)
甚至不使用libc.so
的语言实施示例是Bones Scheme。你可以找到其他几个。
我对VDSO的理解是它是一个抽象,由内核提供,在各个x86处理器系列之间抽象出实现系统调用时的各种小差异(与用户域 - >内核转换相关)。如果您选择了特定的处理器目标,则不需要VDSO,您可以随时避免使用它。
AFAIU,VDSO是一个ELF共享对象,位于ffffffffff600000-ffffffffff601000
段中(在我的Debian / AMD64上,最近编译的3.8.3内核);完全检查cat /proc/self/maps
所在的位置。因此,您只需要了解ELF共享对象的组织并从中检索符号。见this& that个链接。 VDSO使用C约定来调用x86-64 ABI规范中记录的。
也就是说,如果从进程空间中提取VDSO并将其写入磁盘文件,结果就是格式良好的ELF共享对象
ELF是一种记录良好的格式。 x86-64 ABI conventions也是如此
(它精确定义了C调用约定,以及进程'图像的确切开始。另请参见execve(2))手册页,当然还有内核文档,所以我不明白你的问题是什么。我同意理解ELF需要时间(我10年前做过,但我的记忆生疏)。另请阅读计算机上的<elf.h>
标题文件。
例如;运行(在64位Debian x86-64上的zsh
下)
% 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]
另见this answer。
您可能希望在运行时内部使用能够简单地解析VDSO的动态链接器的最小版本。你当然想要了解一个过程开始的确切状态,特别是auxv
,辅助向量的作用(我真的忘记了这些细节,但我记得它们很重要)。参见例如this article
实际上,可靠地启动运行时可能比VDSO问题更难。
您可能还想阅读linux assembly howto,这也解释了一些事情(但更多关于x86而不是x86-64)
顺便说一句,http://musl-libc.org/(这是一个替代libc)的代码更容易阅读和理解(你将很容易地学习它们如何进行动态链接,pthreads等。)答案 1 :(得分:4)
在挖掘互联网时我找到了这个链接
http://www.linuxjournal.com/content/creating-vdso-colonels-other-chicken
我认为它回答了你的问题
答案 2 :(得分:4)
我发现Linux内核树中的这些文件很有用:
Documentation/ABI/stable/vdso
(什么是vDSO对象?)Documentation/vDSO/parse_vdso.c
(vDSO对象的参考解析器)vDSO对象是一个虚拟动态共享对象,始终映射到linux下amd64进程的地址空间。它可用于实现快速系统调用。要访问vDSO对象内的函数,您需要
这两件事都可以通过CC0许可参考实施parse_vdso.c来完成。