查询内核跟踪点的常见指令:
跟踪类eBPF程序主要用于从系统中提取跟踪信息, 进而为监控、排错、性能优化等提供数据支撑。
关于追踪程序主要有下面这四类:
- BPF_PROG_TYPE_KPROBE: 用于对特定函数进行动态插桩, 根据函数位置不同, 又可以分为内核态krpobe和用户态uprobe,但是内核函数和 用户函数的定义属于不稳定的API
- BPF_PROG_TYPE_TRACEPOINT, 用于内核静态工作点,跟踪点可以保持稳定性, 但是不如KPROBE灵活, 无法按需增加新的灵活点
- BPF_PROG_TYPE_PERF_EVENT, 用于性能事件跟踪、包括内核调用、定时器、硬件等各类性能数据
- BPF_PROG_TYPE_RAW_TRACEPOINT/WRITABLE: 用于原始跟踪点
通过上面的介绍相信你对跟踪类eBPF程序已经有所了解了, 下面我们就来介绍一些关于如何查找这些内核跟踪点。
为了方便调试, 内核将所有的函数以及非栈变量的地址都抽取到了/proc/kallsyms
中, 这样调试器就可以根据地址找出对应的函数和变量名称,这样做的好处就是实际含义的名称要比16进制的地址容易读的多
我们可以使用下面这个命令来进行查询:
cat /proc/kallsyms | wc -l
并不是所有的内核函数都是可跟踪的,只有显式导出的内核函数才可以被 eBPF 进行动态跟踪。因而,通常我们并不直接从内核符号表查询可跟踪点,而是使用我接下来介绍的方法
内核调试文件系统向用户空间提供了内核调试所需要的基本信息, 如内核符号列表、跟踪点、函数跟踪(ftrace)状态以及参数格式等
sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_execve/format
但是这个命令, 是基于我们已经知道跟踪的函数是什么的时候, 那我们我们如何获取所有的追踪函数, 我们可以使用bpftrace这个工具
# 查询所有内核插桩和跟踪点
sudo bpftrace -l
# 使用通配符查询所有的系统调用跟踪点
sudo bpftrace -l 'tracepoint:syscalls:*'
使用通配符查询所有名字包含"execve"的跟踪点
sudo bpftrace -l '*execve*'
查看对应程序源码
我们在编写完成对应的程序之后, 如果我们希望去找到对应的程序源码, 此时我们可以使用bpftool这个工具.
首先在命令行中输入下面这个命令, 查看对应的程序列表, 找到对应的程序id
bpftool prog list;
比如我查看到的信息有下面这个:
37: tracepoint tag 89ed9105e10449f4 gpl
loaded_at 2024-04-21T05:10:17+0000 uid 0
xlated 88B jited 70B memlock 4096B
其中37表示程序的标号, 然后tracepoint表示这个是一个跟踪点类型
有了这个eBPF编号之后我们就可以导出整个eBPF程序的指令, 我们可以使用下面这个命令:
//注意这个x是xlated
sudo bpftool prog dump x id 37
然后我们可以输出id对应的bpf指令, 比如显示出下面这个eBPF程序:
int hello_world(void * ctx):
0: (b7) r1 = 33
1: (6b) *(u16 *)(r10 -4) = r1
2: (b7) r1 = 1684828783
3: (63) *(u32 *)(r10 -8) = r1
4: (18) r1 = 0x57202c6f6c6c6548 /* W ,olleH */
6: (7b) *(u64 *)(r10 -16) = r1
7: (bf) r1 = r10
8: (07) r1 += -16
9: (b7) r2 = 14
10: (85) call bpf_trace_printk#-61616
11: (b7) r0 = 0 ;返回值为0
12: (95) exit
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。