【问题标题】:Capture vDSO in strace在 strace 中捕获 vDSO
【发布时间】:2016-11-01 09:31:21
【问题描述】:

我想知道是否有办法在strace 中捕获(换句话说,观察)像gettimeofday 这样的vDSO 调用。

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

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

【问题讨论】:

    标签: linux-kernel system-calls strace vdso


    【解决方案1】:

    您可以使用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&gt;&amp;1 | grep gettimeofday 进行strace:

    09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 &lt;0.000006&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2011-08-11
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2013-06-28
      相关资源
      最近更新 更多