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 部分:
bpflbr
bpf prog,用于采集 LBR 记录。bpflbr
用户态程序,用于解析 LBR 记录。
因为 LBR 记录的是分支跳转记录,所以就需要在 bpflbr
bpf prog 的最前面就调用 bpf_get_branch_snapshot
helper 函数来获取 LBR 记录,避免 bpflbr
bpf prog 本身的分支跳转记录。
|
|
然后,在用户态程序中,读取并解析 LBR 记录:
- 如果是内核函数:
- 通过
/proc/kallsyms
符号表解析函数名。 - 通过
vmlinux
dbgsym 文件解析 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
知识星球
星球里的专栏:
《XDP 进阶手册》
