报错
android 设备部署好ebpf运行环境之后,运行某些bcc工具集自带的工具会导致如下错误
root@localhost:/usr/sbin# cachestat-bpfcc
Traceback (most recent call last):
File "/usr/sbin/cachestat-bpfcc", line 130, in <module>
if BPF.get_kprobe_functions(b'folio_account_dirtied'):
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 708, in get_kprobe_functions
raise e
File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 704, in get_kprobe_functions
with open(avail_filter_file, "rb") as avail_filter_f:
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/sys/kernel/debug/tracing/available_filter_functions'
root@localhost:/usr/sbin#
找不到/sys/kernel/debug/tracing/available_filter_functions 文件,
root@localhost:/usr/sbin# ls -al /sys/kernel/debug/tracing/available_filter_functions
ls: cannot access '/sys/kernel/debug/tracing/available_filter_functions': No such file or directory
root@localhost:/usr/sbin#
root@localhost:/usr/sbin# ls /sys/kernel/debug/tracing
README buffer_size_kb error_log kprobe_events printk_formats set_event trace trace_options tracing_thresh
available_events buffer_total_size_kb events kprobe_profile saved_cmdlines set_event_notrace_pid trace_clock trace_pipe uprobe_events
available_tracers current_tracer free_buffer options saved_cmdlines_size set_event_pid trace_marker tracing_cpumask uprobe_profile
buffer_percent dynamic_events instances per_cpu saved_tgids timestamp_mode trace_marker_raw tracing_on
root@localhost:/usr/sbin#
目录是存在的,但是缺少这个 available_filter_functions 文件
这个文件列出了所有可以被 kprobe、tracepoint 或 perf 使用的内核函数名,是 ftrace(Function Tracer)的一部分。
- BCC 在加载 eBPF 程序时,需要验证用户提供的内核函数名是否合法。
- 它会去读取 /sys/kernel/debug/tracing/available_filter_functions 来检查这些函数是否存在于当前内核中。
- 如果找不到该文件,BCC 就无法进行函数合法性检查,从而抛出异常。
主要是因为有两个ftrace没有打开
root@localhost:/usr/sbin# zcat /proc/config.gz | grep CONFIG_KPROBE_EVENTS
CONFIG_KPROBE_EVENTS=y
root@localhost:/usr/sbin# zcat /proc/config.gz | grep CONFIG_DYNAMIC_FTRACE
root@localhost:/usr/sbin# zcat /proc/config.gz | grep CONFIG_FUNCTION_TRACER
# CONFIG_FUNCTION_TRACER is not set
root@localhost:/usr/sbin#
需要开启 CONFIG_DYNAMIC_FTRACE CONFIG_FUNCTION_TRACER 两个 tracer
解决方案
- 开启上述两个 CONFIG_XXX
- 不使用 /sys/kernel/debug/tracing/available_filter_functions 文件来获取符号, 而是使用 /proc/kallsyms 获取符号
方案一 过于麻烦, 如果仅仅是为了简单工具使用, 去打开config, 编译烧录android 可能需要耗费好几个小时的时间
这里提供一个简单 的方案二
root@localhost:/usr/sbin# python3 -c "import bcc; print(bcc.__file__)"
/usr/lib/python3/dist-packages/bcc/__init__.py
root@localhost:/usr/sbin#
root@localhost:/usr/sbin# cat /usr/lib/python3/dist-packages/bcc/__init__.py | grep available_filter_functions -C 5
except IOError as e:
if e.errno != errno.EPERM:
raise e
blacklist = set([])
avail_filter_file = "%s/tracing/available_filter_functions" % DEBUGFS
try:
with open(avail_filter_file, "rb") as avail_filter_f:
avail_filter = set([line.rstrip().split()[0] for line in avail_filter_f])
except IOError as e:
if e.errno != errno.EPERM:
root@localhost:/usr/sbin#
直接把 抛出异常的 代码屏蔽掉即可, 这个文件后续会使用 /proc/kallsyms 中的符号去验证
root@localhost:/usr/sbin# cat /usr/lib/python3/dist-packages/bcc/__init__.py | grep available_filter_functions -C 7
with open(blacklist_file, "rb") as blacklist_f:
blacklist = set([line.rstrip().split()[1] for line in blacklist_f])
except IOError as e:
if e.errno != errno.EPERM:
raise e
blacklist = set([])
avail_filter_file = "%s/tracing/available_filter_functions" % DEBUGFS
try:
with open(avail_filter_file, "rb") as avail_filter_f:
avail_filter = set([line.rstrip().split()[0] for line in avail_filter_f])
except IOError as e:
# if e.errno != errno.EPERM:
# raise e
avail_filter = set([])
root@localhost:/usr/sbin#
结果
root@localhost:/usr/sbin# cachestat-bpfcc
HITS MISSES DIRTIES HITRATIO BUFFERS_MB CACHED_MB
809 27 0 96.77% 6 1162
383 0 0 100.00% 6 1162
12 0 0 100.00% 6 1162
12 0 0 100.00% 6 1162
392 0 0 100.00% 6 1162
1691 929 0 64.54% 6 1166
0 665 0 0.00% 6 1185
0 2568 0 0.00% 6 1197
2580 190 0 93.14% 6 1198
0 574 0 0.00% 6 1201
630 198 0 76.09% 6 1202
22522 0 0 100.00% 6 1202
39950 749 0 98.16% 6 1206
^C 387 3165 0 10.90% 6 1218
Detaching...
root@localhost:/usr/sbin#