在 strace 中捕获 vDSO
Capture vDSO in strace
我想知道是否有办法捕获(换句话说观察)vDSO 调用,例如 strace
中的 gettimeofday
。
另外,有没有办法在不加载 linux-vdso.so.1
(标志或环境变量)的情况下执行二进制文件?
最后,如果我编写一个程序从辅助向量中删除 linux-vdso.so.1
地址,然后 execve
我的程序呢?有人试过吗?
您可以使用 ltrace
而不是 strace
捕获对通过 vDSO 实现的系统调用的调用。这是因为对通过 vDSO 实现的系统调用的调用与 "normal" 系统调用不同,并且 strace
用于跟踪系统调用的方法不适用于 vDSO 实现的系统调用。要详细了解 strace
的工作原理,请查看 this blog post I wrote about strace. And, to learn more about how ltrace
works, check out this other blog post I wrote about ltrace。
不,不加载 linux-vdso.so.1
就无法执行二进制文件。至少,在我的 libc 版本上 Ubuntu 不精确。 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>
我想知道是否有办法捕获(换句话说观察)vDSO 调用,例如 strace
中的 gettimeofday
。
另外,有没有办法在不加载 linux-vdso.so.1
(标志或环境变量)的情况下执行二进制文件?
最后,如果我编写一个程序从辅助向量中删除 linux-vdso.so.1
地址,然后 execve
我的程序呢?有人试过吗?
您可以使用 ltrace
而不是 strace
捕获对通过 vDSO 实现的系统调用的调用。这是因为对通过 vDSO 实现的系统调用的调用与 "normal" 系统调用不同,并且 strace
用于跟踪系统调用的方法不适用于 vDSO 实现的系统调用。要详细了解 strace
的工作原理,请查看 this blog post I wrote about strace. And, to learn more about how ltrace
works, check out this other blog post I wrote about ltrace。
不,不加载 linux-vdso.so.1
就无法执行二进制文件。至少,在我的 libc 版本上 Ubuntu 不精确。 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>