Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

BPF

CO-RE BTF Libbpf

bpftool 工具

  1. 查看 .bpf.o 中包含的 BTF 信息:

    bpftool btf dump file hello-buffer-config.bpf.o

  2. dump 出 vmlinux.h 头文件,这个头文件包含内核中所有公开结构体。

    bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

  3. 查看已加载 bpf 程序的 debug 信息:

    bpftool -d prog load hello.bpf.o /sys/fs/bpf/hello

    其中 hello.bpf.o 是带调试信息的编译产物,/sys/fs/bpf/hello 是 bpftool 加载 bpf 程序强制要求指定的 bpf 程序挂载点。有这个程序 在文件系统中的挂载点,bpf 程序,才能做到加载到内核中,不 attach 到 实际运行的 hook 点上。没有这个文件系统的挂载点,那么内核中这个 bpf 程序的引用计数会为 0,内核会清零该 bpf 程序。

  4. 生成用户空间程序调用的骨架代码(Skeletons):

    bpftool gen skeleton hello-buffer-config.bpf.o > hello-buffer-config.skel.h

  5. 查看 bpf 特性,jit、内核 CONFIG 等可用的帮助函数等

    bpftool feature

bpf 程序的类型与 attach 类型

bpf 类型定义在头文件 include/uapi/lniux/bfp.henum bpf_prog_type, 大约有三十种 bpf prog type. enum bpf_attach_type 规定了 bpf 程序 attach 的类型。根据 bpf 程序类型不同,该程序能使用的 helper 函数也有所不同,bpf verifier 会做类型与帮助函数的检查,确保 bpf 程序的稳定性。

对于学习内核工作原理、debug、perf 需求来说主要是以下类型需要重点关注:


SYSCSLL        系统调用相关
KPROBE         附加到任意内核函数

TRACING        动态追踪
TRACEPOINT     静态追踪点
RAW_TRACEPOINT 不封装数据的 TRACEPOINT

STRUCT_OPS     替换或扩展内核中特定数据结构
EXT            替换或修改内核函数

表-重点关注的 bpf 程序型

KPROBE

  1. kprobe 的 context paramete 作用于 syscall 的时候,parameter 是用户空间传递到内核空间的结构体。 作用于 nonsyscall 的 kprobe 的 paramter 就是内核中相关函数的参数.

  2. kretprobe 用法与 kprobe 相似,区别在于 kretprobe 在函数返回时触发, 并且可以获取函数的返回值。kprobe 在函数的入口处触发。

  3. fentry/fexit 是 kprobe/kretprobe 新版本内核上更高效的实现。 同时,fexit 相比 kretprobe 可以获取到函数的入参。

  4. uprobe/uretprobe 是对应的 userspace 版本,可以追踪用户空间函数。

TRACEPOINT

查看可用的 tracepoints:

cat /sys/kernel/tracing/available_events

查看 tracepoint 的格式:

cat /sys/kernel/tracing/events/syscalls/sys_enter_execve/format

Python BPF

https://github.com/iovisor/bcc/tree/master/src/python/bcc

Rust Aya

https://github.com/aya-rs/aya

bpftrace

https://github.com/bpftrace/bpftrace

Caveats

  1. clang 优化等级必须是 -O2. 因为 clang 默认的优化等级会使用 call <register> 指令; 然而 ebpf 不支持这条指令。

  2. 必须传递 -g 参数,ebpf 程序需要 debug 信息, 同时也可以使用 llvm-strip -g <objfile> strip 掉 dwarf 信息。

ebpf.io https://docs.ebpf.io

helpers https://man7.org/linux/man-pages/man7/bpf-helpers.7.html

bpf kernel functions https://docs.kernel.org/bpf/kfuncs.html

bpftrace cheat sheet https://www.brendangregg.com/BPF/bpftrace-cheat-sheet.html