在strace中捕获vDSO

时间:2016-06-29 15:10:44

标签: linux-kernel system-calls strace vdso

我想知道是否有办法捕捉(换句话说观察)gettimeofday中的strace等vDSO调用。

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

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

1 个答案:

答案 0 :(得分:6)

您可以使用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地址。避免这种情况的唯一方法是,如果你已经禁用vDSO编译了glibc。

但是,还有另一种解决方法,如果你真的,真的不想使用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进行编译:

09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>