【问题标题】:Getting BPF programs working with USDT probes (Dtrace) in Linux在 Linux 中让 BPF 程序与 USDT 探针 (Dtrace) 一起工作
【发布时间】:2020-10-19 19:38:38
【问题描述】:

所以我正在关注link 将 BPF 程序附加到用户空间探测器,Dtrace 格式(请参阅用户静态定义的跟踪点部分)。

C 程序:

#include <sys/sdt.h>
int main() {
    DTRACE_PROBE("hello-usdt", "probe-main");
}

确保包含探测信息的检查:

readelf -n hello_usdt
  stapsdt              0x00000033   NT_STAPSDT (SystemTap probe descriptors)
    Provider: "hello_usdt"
    Name: "probe-main"
    Location: 0x0000000000400535, Base: 0x00000000004005d4, Semaphore: 0x0000000000000000
    Arguments: 

还有 tplist:

sudo /usr/share/bcc/tools/tplist -l /path/to/hello_usdt
/path/to/hello_usdt "hello_usdt":"probe-main"

BPF 程序的内容(usdt.py):

from bcc import BPF, USDT

bpf_source = """
#include <uapi/linux/ptrace.h>
int trace_binary_exec(struct pt_regs *ctx) {
  u64 pid = bpf_get_current_pid_tgid();
  bpf_trace_printk("New hello_usdt process running with PID: %d", pid);
}
"""

usdt = USDT(path = "./hello_usdt")
usdt.enable_probe(probe = "probe-main", fn_name = "trace_binary_exec")
bpf = BPF(text = bpf_source, usdt = usdt)
bpf.trace_print()

故障描述:

sudo ./usdt.py 
Traceback (most recent call last):
  File "./usdt.py", line 13, in <module>
    usdt.enable_probe(probe = "probe-main", fn_name = "trace_binary_exec")
  File "/usr/lib/python3/dist-packages/bcc/usdt.py", line 154, in enable_probe
    probe
bcc.usdt.USDTException: failed to enable probe 'probe-main';
        a possible cause can be that the probe requires a pid to enable

我也尝试过:

  1. 在 BPF 程序中提供完整的可执行文件 (hello_usdt):

usdt = USDT(path = "/full/path/to/hello_usdt")

  1. 将上面的行替换为 PID 值 (./hello_usdt &),直接在 BPF 程序中获取 pid:

usdt = USDT(pid=1234)

  1. 在安装 python bcc 包后尝试使用 python2.7 和 3.7。

到目前为止没有运气。非常感谢任何帮助。 谢谢。

【问题讨论】:

    标签: linux dtrace bpf ebpf probe


    【解决方案1】:

    我想我知道原来的链接出了什么问题。 我修补了 bcc-tools 的源文件(功能 bcc_usdt_enable_probe 和更深),编译并安装了这个自定义版本,并使用一些 printfs 来跟踪它失败的原因,结果证明在解析探测器列表时,我的程序中定义的探测器被视为带有附加引号的字符串,例如:“”probe-main“”。 所以我换了行:

    DTRACE_PROBE("hello-usdt", "probe-main");
    

    DTRACE_PROBE("hello-usdt", probe-main);
    

    我所做的第二个更改是在 python 脚本中。我没有详述,但看起来这行是错误的(语法):

    bpf = BPF(text = bpf_source, usdt = usdt)
    

    python 编译器抱怨 usdt 未知,然后我发现使用 usdt_contexts=[usdt] 的其他实现。所以我将上面的行替换为:

    bpf = BPF(text = bpf_source, usdt_contexts = [usdt])
    

    在源代码中也替换了探针宏以包含一个额外的时间戳:

    DTRACE_PROBE1("hello_usdt", probe-main, tv.tv_sec);
    

    还更新了 python 脚本:

    #!/usr/bin/python3
    from bcc import BPF, USDT
    
    bpf_source = """
    #include <uapi/linux/ptrace.h>
    int trace_binary_exec(struct pt_regs *ctx) {
      u64 pid = bpf_get_current_pid_tgid();
      u64 ts=0;
      bpf_usdt_readarg(1, ctx, &ts);
      bpf_trace_printk("PROBE-HIT (PID: %d), TS: %lu\\n", pid, ts);
    }
    """
    
    usdt = USDT(path = "/path/to/hello_usdt")
    usdt.enable_probe(probe = "probe-main", fn_name = "trace_binary_exec")
    bpf = BPF(text = bpf_source, usdt_contexts = [usdt])
    bpf.trace_print()
    

    并让它运行起来:

    sudo ./usdt.py
    b'      hello_usdt-18920 [000] .... 300066.568941: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460390'
    b'      hello_usdt-18920 [000] .... 300067.569284: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460391'
    b'      hello_usdt-18920 [000] .... 300068.569509: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460392'
    b'      hello_usdt-18920 [000] .... 300069.569935: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460393'
    b'      hello_usdt-18920 [000] .... 300070.570362: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460394'
    b'      hello_usdt-18920 [000] .... 300083.574478: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460407'
    b'      hello_usdt-18920 [000] .... 300084.574782: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460408'
    b'      hello_usdt-18920 [000] .... 300085.575214: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460409'
    b'      hello_usdt-18920 [000] .... 300086.575630: 0x00000001: PROBE-HIT (PID: 18920), TS: 1593460410'
    

    我不知道为什么原始链接中的实现不同。可能是 BPF/Dtrace 版本的问题,没有详细说明。但是,我没有找到涵盖基本 C 程序的所有步骤的其他实现,但找到了帮助我解决问题的 sn-ps。

    【讨论】:

    • 不错的调试!查看我发现的其他示例,DTRACE_PROBE() 宏的第一个参数可能也不需要引号(所以DTRACE_PROBE(hello-usdt, probe-main);)。关于usdt/usdt_contexts这件事,好像it changed in bcc at some point
    • @Qeole 谢谢,是的,我也注意到了这一点,但它并没有影响功能,但很高兴知道。我找到了大量关于 DTRACE、SystemTap 和 BPF 工具(bcc-tools、bpftrace 等)的文档。对于高级(单行)命令非常清楚,对于实现细节相当稀疏。
    猜你喜欢
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多