【问题标题】:Why are there not any execve calls in my dtruss trace?为什么我的 dtruss 跟踪中没有任何 execve 调用?
【发布时间】:2019-04-18 23:56:37
【问题描述】:

我有一个这样的脚本:

script.sh

#!/bin/bash

clang -v

如果我对其进行dtruss,那么我希望看到execve 调用clang。

$ sudo dtruss -f -a -e ./script.sh 

但是,跟踪不包含execve。而是出现错误:

...
 1703/0x16931:       856       4      0 sigaction(0x15, 0x7FFEE882A3B8, 0x7FFEE882A3F8)      = 0 0
 1703/0x16931:       858       4      0 sigaction(0x16, 0x7FFEE882A3C8, 0x7FFEE882A408)      = 0 0
 1703/0x16931:       874       4      0 sigaction(0x2, 0x7FFEE882A3C8, 0x7FFEE882A408)       = 0 0
 1703/0x16931:       881       4      0 sigaction(0x3, 0x7FFEE882A3C8, 0x7FFEE882A408)       = 0 0
 1703/0x16931:       883       4      0 sigaction(0x14, 0x7FFEE882A3C8, 0x7FFEE882A408)      = 0 0
dtrace: error on enabled probe ID 2149 (ID 280: syscall::execve:return): invalid address (0x7fc2b5502c30) in action #12 at DIF offset 12
 1703/0x16932:      2873:        0:       0 fork()       = 0 0
 1703/0x16932:      2879     138      5 thread_selfid(0x0, 0x0, 0x0)         = 92466 0
 1703/0x16932:      2958       8      0 issetugid(0x0, 0x0, 0x0)         = 0 0
 1703/0x16932:      2975       8      1 csrctl(0x0, 0x7FFEEE21DC3C, 0x4)         = 0 0
 1703/0x16932:      2985      12      6 csops(0x0, 0x0, 0x7FFEEE21E550)      = 0 0
 1703/0x16932:      3100      13      3 shared_region_check_np(0x7FFEEE21DA98, 0x0, 0x0)    
...
  • 是什么导致了这个错误?
  • 如何让execve 命令显示,以便我可以看到调用的程序及其参数?

【问题讨论】:

    标签: macos dtrace dtruss


    【解决方案1】:

    这意味着dtruss 在内部使用的DTrace 脚本正在访问一个无效的内存地址,这发生在它试图跟踪您感兴趣的execve 调用时。所以基本上,dtruss(或者可能是 DTrace 本身)似乎有一个错误,它会阻止您获取所需的信息。不幸的是,Apple 在保持 DTrace 和依赖它的工具在 macOS 上运行良好方面并不是最好的:-/。

    特别是对于 Bash / shell 脚本,您可以通过在脚本顶部添加 set -x 使其打印运行的每个命令(更多信息 in this other answer)。

    如果您愿意,您也可以尝试直接使用 DTrace - 这是一个非常简单的单行程序(我自己没有尝试过运行,如果有错别字,敬请见谅):

    sudo dtrace -n 'proc:::exec-success /ppid == $target/ { trace(curpsinfo->pr_psargs); }' -c './script.sh'
    

    它的工作方式是:

    • proc:::exec-success:跟踪系统中的所有exec-success 事件,当exec*-family 系统调用成功返回时在子进程中触发。
    • /ppid == $target/:过滤器,这意味着只有当父进程的 PID (ppid) 与我们传递给 dtrace 命令 ($target) 的 -c 选项启动的进程返回的 PID 匹配时才会触发。李>
    • { trace(curpsinfo->pr_psargs); }:这是在事件触发并匹配我们的过滤器时采取的操作。我们只需打印 (trace) 传递给进程的参数,这些参数存储在 curpsinfo 变量中。

    (如果失败并出现类似的错误,则该错误很可能存在于 macOS 的 curpsinfo 实现中。)

    【讨论】:

    • 好答案。我相信,这里问题的实际原因是dtruss 将execve 的arg0(path 指针)在入口 上抓取到execve 系统调用,然后尝试将其打印为来自execve 系统调用的字符串指针on exit。但是由于execve完全替换了进程的地址空间,系统调用后指针不再有效。因为指针在成功的execve 中无效,所以dtruss 需要(但缺少)execve 系统调用的特殊情况。
    • 啊,果然!我一直以为是编译好的程序,不是脚本,所以不知道你能看源码。作为参考,我也在网上找到了它:opensource.apple.com/source/dtrace/dtrace-147/DTTk/….
    猜你喜欢
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    相关资源
    最近更新 更多