eBPF Talk: bpfsnoop v0.4.0 发布
文章目录
bpfsnoop
是一款 bpf 时代的现代化内核函数、内核跟踪点和 bpf 程序的动态追踪工具。
bpfsnoop
发布 v0.4.0 版本,主要更新如下:
- 使用
kprobe
动态追踪内核函数的所有指令。 - 实现了一个基于 BTF 的 C 表达式编译器。
- 为
--output-arg
新增指针内容、buf()
内置函数和str()
内置函数。 - 复用
ringbuf
传递函数参数、函数返回值和所有匹配的--output-arg
。
bpfsnoop
官网:bpfsnoop.com
使用 kprobe
动态追踪内核函数的所有指令
bpfsnoop
使用 capstone-engine 来反汇编内核函数的所有指令,然后使用 kprobe
来动态追踪内核函数的所有指令。
效果如下:
|
|
P.S. BPF 程序不允许使用 kprobe
来动态追踪程序的所有指令。
实现了一个基于 BTF 的 C 表达式编译器
bpfsnoop
实现了一个基于 BTF 的 C 表达式编译器,支持使用复杂的 C 表达式来过滤和获取函数参数的属性。
效果如下:
|
|
支持以下操作符:
- Limited support for memory access via ‘.’, ‘->’, ‘array[idx]’, ‘& (get addr)’ and ‘* (access data of pointer)’.
- Bitwise and ‘&’.
- Bool and ‘&&’.
- Ternary condition ‘?:’.
- Math div ‘/’.
- Bool equal ‘==’.
- Bool greater than ‘>’.
- Bool greater than or equal ‘>=’.
- Bitwise left shift ‘«’.
- Bool less than ‘<’.
- Bool less than or equal ‘<=’.
- Unary minus ‘-’.
- Math mod ‘%’.
- Math multi ‘*’.
- Internal constants ’true’, ‘false’ and ‘NULL’.
- Variable from function’s arguments.
- Unary bool not ‘!’.
- Bool not equal ‘!=’.
- Constant number, including hex, oct, bin, decimal and char.
- Bitwise or ‘|’.
- Bool or ‘||’.
- Parentheses ‘()’.
- Unary plus ‘+’.
- Pre-decrement ‘–’.
- Pre-increment ‘++’.
- Bitwise right shift ‘»’.
- Math sub ‘-’.
- Bitwise twid ‘~’.
- Bitwise xor ‘^’.
而且,它们的优先级遵循 C 语言的优先级规则。
为 --output-arg
新增指针内容、buf()
内置函数和 str()
内置函数
使用 ringbuf
传递 --output-arg
的数据后,--output-arg
数据的大小不再有限制(理论上最大为 64MiB),因此可以输出指针内容,比如完整的结构体。
效果如下:
|
|
结构体内容的输出,复用了 eBPF Talk: 谁动了我的 bpf map? 里 mad 的功能。
与此同时,给 --output-arg
新增了 buf()
内置函数和 str()
内置函数。
buf()
内置函数
buf()
内置函数有 2 种用法:
buf(ptr, size)
:输出指针ptr
指向的内存区域的内容,大小为size
字节。buf(ptr, offset, size)
:输出指针ptr
指向的内存区域的内容,偏移量为offset
,大小为size
字节。
效果如下:
|
|
str()
内置函数
str()
内置函数有 2 种用法:
str(array)
:输出字符串数组array
的字符串。str(ptr, size)
:输出指针ptr
指向的内存区域的字符串,大小为size
字节。
效果如下:
|
|
复用 ringbuf
传递函数参数、函数返回值和所有匹配的 --output-arg
这是一次受益巨大的重构,既提升了可扩展性,又简化了代码,还少用了 5 个 bpf map。
因为 bpfsnoop
会为每个被动态追踪的对象都使用独立的 bpf prog,因而可以通过 volatile const struct config {...}
来传递函数参数、函数返回值和所有匹配的 --output-arg
等数据的字节数量;然后,根据 [event | args and retval | output args]
的格式来输出数据。
|
|
在 Go 里,按需解析事件数据:
|
|
总结
bpfsnoop
v0.4.0 版本的发布,主要是为了提升可扩展性和简化代码,同时也增加了对内核函数所有指令的动态追踪、基于 BTF 的 C 表达式编译器、指针内容输出、buf()
和 str()
内置函数等功能。
bpfsnoop
是一款 bpf 时代的现代化内核函数、内核跟踪点和 bpf 程序的动态追踪工具:
- 支持输出 LBR 记录。
- 支持反汇编内核函数和 bpf prog。
- 支持输出函数调用栈。
- 支持输出带类型信息的参数和带类型的返回值。
- 支持使用复杂的 C 表达式来过滤函数参数的属性。
- 支持根据函数参数来过滤需要动态追踪的内核函数列表。
- 支持使用 pcap-filter(7) 语法来过滤网络包。
- 支持
--output-pkt
输出网络包里的五元组信息。 - 支持动态追踪多达 12 个参数的内核函数。
- 支持
--output-arg
来输出函数参数的属性,类似于--filter-arg
。 - 支持
--output-flamegraph
来输出火焰图的折叠后的数据。 - 支持
-t
来动态追踪内核跟踪点。 - 在
-k
里支持 ‘(i)’ 前缀来动态追踪内核函数的所有指令。 - 支持
--output-arg
来输出指针内容、buf()
内置函数和str()
内置函数。
未来将支持更多高级功能,敬请期待!
bpfsnoop
项目地址:bpfsnoop。
文章作者 Leon Hwang
上次更新 2025-05-26
知识星球
星球里的专栏:
《XDP 进阶手册》
