您可以使用ltrace 而不是strace 来捕获对已通过vDSO 实现的系统调用的调用。这是因为对通过 vDSO 实现的系统调用的调用与“正常”系统调用的工作方式不同,并且strace 用于跟踪系统调用的方法不适用于 vDSO 实现的系统调用。要了解有关strace 工作原理的更多信息,请查看this blog post I wrote about strace。此外,要详细了解 ltrace 的工作原理,请查看 this other blog post I wrote about ltrace。
不,不加载linux-vdso.so.1 就无法执行二进制文件。至少,不是我在 Ubuntu 上的 libc 版本精确。较新版本的 libc/eglibc/etc 肯定有可能将其添加为功能,但似乎不太可能。请参阅下一个答案了解原因。
如果您从辅助向量中删除地址,您的二进制文件可能会崩溃。 libc 有一个piece of code,它将首先尝试遍历 vDSO ELF 对象,如果失败,将回退到硬编码的 vsyscall 地址。避免这种情况的唯一方法是在编译 glibc 时禁用 vDSO。
不过,如果您真的不想使用 vDSO,还有另一种解决方法。您可以尝试使用glibc's syscall function 并传入gettimeofday 的系统调用号。这将强制 glibc 通过内核而不是 vDSO 调用 gettimeofday。
我在下面包含了一个示例程序来说明这一点。您可以阅读我的syscall blog post,了解有关系统调用如何工作的更多信息。
#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 -ttTf ./test 2>&1 | grep gettimeofday 进行strace:
09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>