9

我想知道是否有一种方法可以捕获(换句话说,观察)vDSO 调用,例如gettimeofdayin strace

另外,有没有办法在不加载linux-vdso.so.1(标志或环境变量)的情况下执行二进制文件?

最后,如果我编写一个程序linux-vdso.so.1从辅助向量中删除地址然后execve我的程序呢?有人试过吗?

4

1 回答 1

8

您可以使用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>

于 2016-06-30T16:59:50.717 回答