最近的Linux内核(至less在amd64上)提供了一个名为linux-vdso.so.1
的魔术对象文件linux-vdso.so.1
内核的系统调用接口抽象出来,允许内核select最佳的调用约定。 如果你用C写代码,glibc会自动使用这个对象。
现在,如果我想写一个程序而不使用glibc,我该如何使用这个对象呢? 它提供的接口是在什么地方logging的? 怎么样的调用约定?
这取决于您的实现是否使用低级别的实用程序的C接口。
如果你的语言直接访问系统调用而不通过C封装,你不需要使用VDSO(例如,你可以生成相应的SYSENTER
机器指令来执行系统调用)。 在这种情况下,你的语言甚至不需要遵循所有的ABI约定,只是内核的约定。 (例如,你不需要ABI提供的调用者安全的calle-safe区别寄存器,你甚至可以避免使用任何堆栈)。
我对VDSO的理解是,它是由内核提供的一个抽象,用来抽象出各个x86处理器系列之间在执行系统调用时的各种微小差异(与用户 – 地址 – >内核转换有关)。 如果您选择了特定的处理器目标,则不需要VDSO,并且始终可以避免这种情况。
AFAIU,VDSO是一个ELF共享对象,位于ffffffffff600000-ffffffffff601000
段(在我的Debian / AMD64上有一个最近编译的3.8.3内核); 检查完全与cat /proc/self/maps
)。 所以你只需要了解ELF共享对象的组织,并从中检索符号。 看到这个和那个链接。 VDSO使用x86-64 ABI规范中记录的C约定进行调用。
也就是说,如果从进程空间中提取VDSO并将其写入磁盘文件,那么结果是一个格式良好的ELF共享对象
ELF是一个有据可查的格式。 x86-64 ABI约定也是如此(它精确地定义了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]
另请参阅此答案 。
您可能需要在您的运行时间内使用动态链接程序的最小版本来简单地解析VDSO。 你当然想要了解进程开始的确切状态,特别是辅助向量(辅助向量)的作用(我真的忘记了这些细节,但是我记得它们很重要)。 见例如这篇文章
实际上,可靠地开始运行可能比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完成 。