eBPF Talk: 使用 Last Branch Record 动态追踪内核函数
文章目录
Last Branch Record,简称 LBR,是 CPU 提供的一种硬件功能,可以记录程序执行过程中的分支跳转信息;目前,Intel CPU、AMD CPU 均已支持 LBR 功能;Linux 内核正在支持 ARM CPU 的分支跳转记录功能。
即使是个人电脑的 Intel CPU,也支持 LBR 功能:
|  |  | 
LBR 的资料请参考:
- Intel® 64 and IA-32 Architectures Software Developer Manuals
- An introduction to last branch records
- Advanced usage of last branch records
尽管不清楚 LBR 的工作原理,并不妨碍用来追踪内核函数;甚至可以用来追踪 bpf prog 的内部执行细节。
在 bpf 中,从 commit (“bpf: Introduce helper bpf_get_branch_snapshot”) v5.16 内核开始,引入了 bpf_get_branch_snapshot helper 函数,可以获取当前 CPU 的 LBR 记录。
bpflbr 便是使用 bpf_get_branch_snapshot helper 实现的 LBR 追踪工具,可以追踪内核函数的调用关系,以及 bpf prog 的执行细节。
bpflbr: 实现原理讲解
bpflbr 分 2 部分:
- bpflbrbpf prog,用于采集 LBR 记录。
- bpflbr用户态程序,用于解析 LBR 记录。
因为 LBR 记录的是分支跳转记录,所以就需要在 bpflbr bpf prog 的最前面就调用 bpf_get_branch_snapshot helper 函数来获取 LBR 记录,避免 bpflbr bpf prog 本身的分支跳转记录。
|  |  | 
然后,在用户态程序中,读取并解析 LBR 记录:
- 如果是内核函数:
- 通过 /proc/kallsyms符号表解析函数名。
- 通过 vmlinuxdbgsym 文件解析 line info。
 
- 通过 
- 如果是 bpf prog:
- 事先解析所有 bpf prog 的信息,包括函数名、line info。
 
- 通过 LBR 记录输出分支跳转信息。
更详细的源代码讲解:eBPF 项目源码分析-BPFLBR。
bpflbr: 功能列表
bpflbr 已经实现了以下功能:
- 使用 fexit动态追踪 bpf prog 的内部执行细节。
- 使用 fentry动态追踪 bpf prog 执行前的内核函数分支跳转记录。
- 使用 fexit动态追踪内核函数的内部执行细节。
- 使用 fentry动态追踪内核函数执行前的分支跳转记录。
- 通过 --output-stack输出函数调用栈。
- 默认输出函数参数、函数返回值的详细信息。
- 通过 capstone-engine 反汇编内核函数和 bpf prog。
|  |  | 
bpflbr: LBR 功能展示
使用 fexit 动态追踪 bpf prog 的内部执行细节:

使用 fentry 动态追踪 bpf prog 执行前的内核函数分支跳转记录:

bpflbr: 输出函数调用栈

bpflbr: 反汇编 bpf prog

bpflbr: 反汇编内核函数

bpflbr: 将具备更加强大的功能
计划将 eBPF Talk: 动态过滤函数参数 的能力整合进 bpflbr,使得可以动态过滤函数参数;甚至使用 pcap-filter(7) 的语法来过滤 skb/xdp 数据包。
并打算参考 bice 的原理,动态输出结构体/联合体指针函数参数的指定字段。
总结
bpflbr 是一个使用 LBR 功能追踪内核函数和 bpf prog 的工具,可以输出函数调用栈、函数参数、函数返回值的详细信息,还可以反汇编内核函数和 bpf prog。
bpflbr 的源代码在 bpflbr。
文章作者 Leon Hwang
上次更新 2025-02-23
