写了一个基于 eBPF 和二进制调试信息的用户态追踪工具,站在 GDB 肩膀上,但可以对线上服务实时追踪 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
swananan
V2EX    程序员

写了一个基于 eBPF 和二进制调试信息的用户态追踪工具,站在 GDB 肩膀上,但可以对线上服务实时追踪

  •  
  •   swananan
    swananan 6 天前 1569 次点击
    项目地址: https://github.com/swananan/ghostscope

    大家感兴趣可以看 README 的演示,我目前可以拿来跟踪 nginx 进程,用的还是蛮顺手的,这个工具我想了好久了,特别是 TUI 操作的时候,加上了我喜欢的 cgdb 、tmux 、vim 甚至还有 emacs 等工具的一些操作风格和按键习惯。所以,我在开发的时候,还是蛮开心的。

    想做这个工具,主要是我以前排查问题的时候,总是觉得日志不够用,但是线上服务,又不能随便发版本,各种红线和变更要求,条条框框卡的很死。我好久以前尝试拿着 systemtap ,根据调试信息去抓线上我想看的信息,属于强行死马当活马医(问题如果拖着不查,后面暴雷了也是一个死)。记得,我当时测试机跑宕机了两次,我才敢拿着 systemtap 脚本去小流量机器偷偷抓信息。现在 eBPF + uprobe 的抓取方式,至少安全性是靠谱的。

    不过目前项目还在启动阶段,有蛮多的限制,具体文档有写。我这边简单提两句,对 c 语言支持比较好(有点废话的意思),至于 C++、Rust 的话,目前只简单支持了 mangled 查找,各种高级语言特性完全不支持。另外,对于编译器开了高优化的程序,探测能力还有待后续增强,各种内联,调试信息 DWARF 复杂好多,搞得我头大。

    大家有什么想法,欢迎开 issue 或者在帖子留言,我还在疯狂迭代,准备先让自己觉得好用,后面再看下一步迭代方向。
    14 条回复    2025-10-14 22:03:10 +08:00
    faketemp
        1
    faketemp  
       5 天前 via iPhone
    请问下对比 bpftrace 在使用方法和功能等方面有哪些优势?另外 windows 系统下除了 frida 有没有类似大佬这种可以实时追踪的工具推荐?
    illios
        2
    illios  
       5 天前   1
    Very impressive work ! STARed on github
    bv
        3
    bv  
       5 天前
    swananan
        4
    swananan  
    OP
       5 天前
    @faketemp
    问题 1:这是个很好的问题哈,我这边做个回答(晚上我整理一下,给放到项目 QA 文档里面)。
    a. bpftrace 在最近的版本变动里面去掉了对 DWARF 也就是调试信息的支持( https://github.com/bpftrace/bpftrace/pull/3921 )。这也是我想启动这个项目的一个原因之一。

    b. bpftrace 对 DWARF 的使用,应该是局限在复杂数据结构的内存布局上面,增强对复杂数据结构的访问。但是,bpftrace 只支持了函数入口和函数返回这种 hook 点,没有完全利用 DWARF 的能力。比如说,某一行源码对应的指令,被探测程序执行到这个指令时候,局部变量,全局变量,参数究竟在内存的哪里。这些是需要根据 DWARF 里面的表达式进行实时求值,才能获取到的。这意味着 bpftrace 其实无法具备类似于 GDB 那样基于 DWARF 提供完整的用户态探测调试的能力。 (我对 bpftrace 代码了解的很粗浅,只是以前快速翻了一下,有错误随时指正哈)

    c. ghostscope 参考 GDB 对 DWARF 的处理,并且把 DWARF 表达式实时生成 LLVM IR ,然后通过 LLVM 生成 eBPF 字节码。这样的话,理论上 ghostscope 是可以根据 DWARF 描述的信息,在用户关注的指令流程上,抓取正确的二进制数据,并且正确的根据 DWARF 信息展示出二进制数据对应源代码的样子。当然,因为 ghostscope 底层依赖的是 eBPF + uprobe ,而不是像 GDB 那样使用 ptrace ,所以不能提供交互式 debug 的体验,但是不影响进程服务运行,而获取关键信息的能力,在很多时候是很有用的。

    d. ghostscope 提供了我个人非常喜欢的 TUI 使用方式,类似于 cgdb ,哈哈,我是真的喜欢 cgdb ,我觉得也许也会有其他人喜欢吧。

    问题 2:我不太懂 Windows 系统,我甚至还没有去了解 Windows eBPF 的进展( https://github.com/microsoft/ebpf-for-windows ),也不太清楚 Windows 有没有类似 uprobe 的机制。但是我有一个想法,就是类似 bpftime 的方式,hack 进用户态进程里面,然后执行 eBPF 脚本。不晓得有没有类似的项目在做这件事情。如果我把 ghostscope 打磨稳定(支持好编译高优化程序的 DWARF 、支持栈回溯、支持 Rust 或者 C++ 的一些高级特性),我可能会开始考虑跨平台方案。我还在学习的路上,工作也不是专门做这块的,所以应该还是要踩坑和探索好久。
    swananan
        5
    swananan  
    OP
       5 天前
    @bv 感谢提醒,我说为啥 workflows 一直没跑,我以为是需要充钱,哈哈,我晚上回去处理一下。
    我第一次发布工具类的项目,我本意是想尽量支持更多的系统版本,所以我选了 Ubuntu 20.04 来进行构建。
    现在的话,我是通过 docker 来构建的(还是基于 Ubuntu 20.04 ),然后构建的二进制 tar 包在 Release 页面里面。
    csfreshman
        6
    csfreshman  
       5 天前   1
    已 star ,有空学习下
    buleLi
        7
    buleLi  
       5 天前
    这里使用了 uprobe ,那启动时实际上会造成目标进程的上下文切换,如果 attach 的位置是一个高频函数,那性能影响应该比较大?
    zzz22333
        8
    zzz22333  
       5 天前
    有点意思,我之前尝试用 ftrace+kprobe 去抓函数传入的参数,但是效果不尽人意。
    wsszh
        9
    wsszh  
       5 天前
    厉害了,学习下
    zzz22333
        10
    zzz22333  
       5 天前   1
    @zzz22333 #8 我也喜欢用 cgdb ,我研究研究,看后续加点 feature
    swananan
        11
    swananan  
    OP
       5 天前
    @buleLi 是的,如果在热点路径加,性能影响会比较大,本质上这个开销比起代码中打印日志,还多了上下文切换。不过,调试排查问题,不太应该在热点路径狂加日志(至少加点过滤条件)。后续优化的话,比较倾向于接入 bpftime ,来避免上下文切换的开销。
    swananan
        12
    swananan  
    OP
       5 天前 via iPhone
    @zzz22333 欢迎欢迎,我挺喜欢 cgdb 模式切换,以及源码上直接加断点的(虽然这么一说,平平无奇的样子),但是 vim 风格操作我非常喜欢
    zzz22333
        13
    zzz22333  
       5 天前 via Android
    @swananan 我是之前同事推荐的,cgdb 操作跟 vim 差不多,我是分了左右界面,左边看代码,右边操作
    FrankAdler
        14
    FrankAdler  
       4 天前 via Android   1
    支持一下,感觉 ebpf 这几年用的变多了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     880 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 21ms UTC 20:21 PVG 04:21 LAX 13:21 JFK 16:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86