在strace中捕获vDSO

Ana*_*dis 7 system-calls linux-kernel strace vdso

我在想,如果有一种方法来捕获(即观察)VDSO调用像gettimeofdaystrace.

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

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

Joe*_*ato 6

您可以使用ltrace代替来捕获已通过vDSO实现的系统调用的调用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.这将强制glibc gettimeofday通过内核而不是vDSO调用.

我在下面列出了一个示例程序来说明这一点.您可以通过阅读我的系统调用博客文章,详细了解系统调用的工作原理.

#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;
}
Run Code Online (Sandbox Code Playgroud)

编译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>