我想知道是否有一种方法可以捕获(换句话说,观察)vDSO 调用,例如gettimeofday
in strace
。
另外,有没有办法在不加载linux-vdso.so.1
(标志或环境变量)的情况下执行二进制文件?
最后,如果我编写一个程序linux-vdso.so.1
从辅助向量中删除地址然后execve
我的程序呢?有人试过吗?
我想知道是否有一种方法可以捕获(换句话说,观察)vDSO 调用,例如gettimeofday
in strace
。
另外,有没有办法在不加载linux-vdso.so.1
(标志或环境变量)的情况下执行二进制文件?
最后,如果我编写一个程序linux-vdso.so.1
从辅助向量中删除地址然后execve
我的程序呢?有人试过吗?
您可以使用ltrace
而不是strace
. 这是因为对通过 vDSO 实现的系统调用的调用与“正常”系统调用的工作方式不同,并且strace
用于跟踪系统调用的方法不适用于 vDSO 实现的系统调用。要了解有关其strace
工作原理的更多信息,请查看我撰写的有关 strace 的博客文章。而且,要了解有关其ltrace
工作原理的更多信息,请查看我写的关于 ltrace 的另一篇博文。
不,不加载就无法执行二进制文件linux-vdso.so.1
。至少,不是我在 Ubuntu 上的 libc 版本精确。较新版本的 libc/eglibc/etc 肯定有可能将其添加为功能,但似乎不太可能。请参阅下一个答案以了解原因。
如果您从辅助向量中删除地址,您的二进制文件可能会崩溃。libc 有一段代码将首先尝试遍历 vDSO ELF 对象,如果失败,将回退到硬编码的 vsyscall 地址。避免这种情况的唯一方法是在禁用 vDSO 的情况下编译 glibc。
但是,如果您真的不想使用 vDSO,还有另一种解决方法。您可以尝试使用glibc 的syscall
函数并传入gettimeofday
. 这将强制 glibcgettimeofday
通过内核而不是 vDSO 调用。
我在下面包含了一个示例程序来说明这一点。您可以通过阅读我的syscall 博客文章来了解有关系统调用如何工作的更多信息。
#include <sys/time.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
int
main(int argc, char *argv[]) {
struct timeval tv;
syscall(SYS_gettimeofday, &tv);
return 0;
}
编译gcc -o test test.c
并使用 strace strace -ttTf ./test 2>&1 | grep gettimeofday
:
09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>