如何根据oops函数偏移快速定位源码?
如何根据函数偏移快速定位源码?
在内核栈的输出中,你一定注意到每一个函数的输出格式都是函数名+偏移量
,而这儿的偏移就是调用下一个函数的位置。那么,能不能根据函数名+偏移量
直接定位源码的位置呢?
答案是肯定的。这是因为,不仅是我们这些 eBPF 学习者想要这种工具,内核开发者为了方便问题的排查,也经常需要根据内核栈,快速定位导致问题发生的代码位置。所以,Linux 内核维护了一个 faddr2line 脚本,根据函数名+偏移量
输出源码文件名和行号。你可以点击这里,把它下载到本地,然后执行下面的命令加上可执行权限:
$chmod +x faddr2line
注意内核编译配置需要启用CONFIG_DEBUG_INFO!!
在使用这个脚本之前,你还需要注意两个前提条件:
-
第一,带有调试信息的内核文件,一般名字为 vmlinux(注意,/boot 目录下面的 vmlinz 是压缩后的内核,不可以直接拿来使用)。
-
第二,系统中需要安装 awk、readelf、addr2line、size、nm 等命令。
对于第二个条件,这些命令都包含在 binutils 软件包中,只需要执行 apt 或者 dnf 命令安装即可。
而对第一个条件中的内核调试信息,各个主要的发行版也都提供了相应的软件仓库,你可以根据文档进行安装。比如,对于 Ubuntu 来说,你可以执行下面的命令安装调试信息:
codename=$(lsb_release -cs)
sudo tee /etc/apt/sources.list.d/ddebs.list << EOF
deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse
EOF
sudo apt-get install -y ubuntu-dbgsym-keyring
sudo apt-get update
sudo apt-get install -y linux-image-$(uname -r)-dbgsym
就可以执行下面的命令,对刚才内核栈中的 __ip_local_out+219
进行定位:
$faddr2line /usr/lib/debug/boot/vmlinux-5.13.0-22-generic __ip_local_out+219
命令执行后,可以得到下面的输出:
__ip_local_out+219/0x150:
nf_hook at include/linux/netfilter.h:256
(inlined by) __ip_local_out at net/ipv4/ip_output.c:115
- 第二行表示
nf_hook
的定义位置在netfilter.h
的156行。 - 第三行表示
net/ipv4/ip_output.c
的 115行调用了kfree_skb
函数。但是,由于nf_hook
是一个内联函数,所以行号115实际上是内联函数 nf_hook 的调用位置。
make -C /lib/modules/$(uname -r)/build M=/lib/modules/$(uname -r)/kernel/drivers/my_module modules
GNU C预定义了一系列的宏,这些宏都是以双下划线开始的
查看内置宏的命令
gcc -dM -E - < /dev/null
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义