在bpfTrace中使用USDT

内核 专栏收录该内容
8 篇文章 0 订阅

在这里插入图片描述本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。

引言

USDT的全称是user-level statically defined tracing,是一种在用户态中埋点,以支持动态追踪的方案,埋点的优点基本可以阐述为以下三点:

  1. 防止inline而导致无法监测到函数
  2. 随版本迭代接口功能可以保证没有变化
  3. 在不进行追踪时插入一条nop指令,在进行追踪时替换为int3。在不追踪时最大程度节省性能,代价只是一条nop和elf文件中多一个NOTE段,其中存储着probe的一些偏移信息。

不过目前这种USDT的埋点方案我还没有找到如何在SystemTap去使用([3]中描述量一种情况),[1]中描述了systemTap中usdt的使用,我们这篇来看一看如何在bpfTrace中使用USDT,这里我们使用Folly中的Traceing工具(folly/tracing)去实现需求,这里其实Folly中只用到了StaticTracepoint-ELFx86.hStaticTracepoint.h这两个文件而已,所以我们完全可以把这两个文件直接拷贝到我们的项目中,使得项目原生支持USDT。

例子

我们先看一个简单的例子:

#include "StaticTracepoint.hpp"
#include <unistd.h>

int main() {
    sleep(5);
    int one = 10;
    int two = 20;
    for (size_t i = 0; i < 100; i++) {
        one = two = i;
        TRACING_SDT(lizhaolong, yunwenqi, one, two);
    }
    sleep(10000);
    return 0;
}

执行如下指令g++ -fno-omit-frame-pointer -O0 -g main.cpp,然后我们gdb进去看看汇编,执行disassemble /m main就可以看到函数对应的源码和汇编了:
在这里插入图片描述
我们可以看到bpfTrace没有开始追踪时,这个地方是一条空指令,因为StaticTracepoint-ELFx86.h中插入汇编时有一条__volatile__,所以这个nop指令也不会被优化。

当我们把bpfTrace挂上时,即执行如下指令sudo bpftrace -e 'usdt:/home/lizhaolong.lzl/usdt/a.out:lizhaolong:yunwenqi {printf("%d %d\n", arg0, arg1)}',我们可以看到这样的输出:
在这里插入图片描述
此时gdb进去,可以看到如下显示:
在这里插入图片描述
这里其实就是去利用uprobes去执行动态追踪了。

我们也可以在elf文件中看到probe已经存在的证据:
在这里插入图片描述
好巧不巧,这里的Location的偏移就是我们设定的probe的起始地址,后面还有后面要提的信号量的偏移。


除了正常的埋点意外,还可以把代码写成下面这样:

#include "StaticTracepoint.hpp"
#include <unistd.h>

// 必须放到全局变量处,这是一个信号量的声明,有extern "C" 前缀
TRACING_SDT_DEFINE_SEMAPHORE(lizhaolong, yunwenqi)

int main() {
    sleep(5);
    int one = 10;
    int two = 20;
    for (size_t i = 0; i < 100; i++) {
        one = two = i;
        if (TRACING_SDT_IS_ENABLED(lizhaolong, yunwenqi)) {
            one *= 10;
            two *= 10;
            TRACING_SDT_WITH_SEMAPHORE(lizhaolong, yunwenqi, one, two);
        }
    }
    sleep(10000);
    return 0;
}

其实就是可能在把参数传向probe时可能需要做一些处理,这些处理可能是比较昂贵的,所以自然没有被追踪时我们不希望这些代码被执行,此时可以设定一个信号量,在被追踪时才被设置,其实本质就是一个volatile unsigned short
在这里插入图片描述
在这里插入图片描述
我们可以看到信号量的地址其实已经是写在elf文件中了的。此时我们用一个if判断跳过了昂贵的参数处理过程。

参考:

  1. https://github.com/agentzh/usdt-sample
  2. https://github.com/facebook/folly
  3. Adding User Space Probing to an Application (heapsort example)
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:撸撸猫 设计师:马嘣嘣 返回首页

打赏作者

李兆龙的博客

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值