如何查找eBPF可用的系统调用?以__x64_sys_tcp_connect为例
为啥你找不到__x64_sys_tcp_connect?
先搞清楚:__x64_sys_tcp_connect不是标准系统调用名,它是x86_64架构下内核系统调用的包装函数前缀。你之前没查到,大概率是内核版本、编译配置(比如CONFIG_FTRACE_SYSCALLS开关)的差异,或者这个符号本身就不是标准系统调用入口,而是内核内部的TCP相关函数。
靠谱的查找方法
1. 直接扒内核导出符号
用cat /proc/kallsyms | grep "__x64_sys_"过滤x86_64的系统调用入口函数。这个文件里有内核所有导出的符号,能直接确认__x64_sys_tcp_connect是否存在。
提示:有些内核默认隐藏kallsyms内容,得用
sudo cat /proc/kallsyms才能看全,或者先挂载debugfs(mount -t debugfs none /sys/kernel/debug)。
2. 区分标准系统调用和内核内部函数
标准系统调用里只有connect,没有tcp_connect。你碰到的__x64_sys_tcp_connect要么是内核补丁/自定义内核加的,要么是内核内部的TCP处理函数:
- 查标准
connect系统调用:grep -r "connect" /arch/x86/entry/syscalls/syscall_64.tbl,对应的内核入口应该是__x64_sys_connect。 - 查内核内部TCP函数:
cat /proc/kallsyms | grep "tcp_connect",如果存在这个符号,哪怕不是系统调用,也能用kprobe追踪。
3. 用bpftool精准找可追踪函数
比bpftrace -l更靠谱的是bpftool probe list functions | grep -E "(sys_|tcp_connect)",这个工具能直接列出所有可以被kprobe附着的内核函数,包括系统调用入口和内部逻辑函数。
4. 核对内核编译配置
有些编译选项会影响符号的命名和可见性:
- 检查
CONFIG_HAVE_SYSCALL_WRAPPERS是否开启,开了之后系统调用才会有__x64_sys_前缀的包装函数。 - 确认
CONFIG_KPROBES是开启的,这是用kprobe的前提。
5. 换个思路追踪TCP逻辑
如果目标是监控TCP连接,不一定非要卡着tcp_connect。标准内核里的tcp_v4_connect、tcp_v6_connect这些函数是肯定存在的,更容易找到,用kprobe追踪这些反而更稳定。
总结一下
- 先分清系统调用入口(带
__x64_sys_前缀,对应标准syscall)和内核内部函数(比如TCP相关的处理函数)的区别。 - 优先用
/proc/kallsyms和bpftool找真实存在的符号,别死磕示例里的函数名——示例可能是基于特定内核版本写的。 - 核对内核的编译配置,避免因为开关导致符号不可见。
内容的提问来源于stack exchange,提问作者clive

