linux内核调试工具-addr2line和gdb定位问题
程序员文章站
2022-06-03 22:33:23
...
之前没有用过addr2line和gdb等内核调试工具定位问题代码,这里记录一下在将某个网络驱动从4.9内核移植到5.7内核时出现内核崩溃起不来的问题。
4.9内核到5.7内核改动了大量代码,在将驱动移植到5.7上编译到内核里时出现了很多错误,按照错误提示都解决之后(网络相关函数有变动),编译通过,系统起到一半内核崩溃,错误提示如下
[ 2.547487] ------------[ cut here ]------------
[ 2.547508] WARNING: CPU: 3 PID: 54 at ethtool_check_ops+0x18/0x38
[ 2.552581] Modules linked in:
[ 2.555601] CPU: 3 PID: 54 Comm: kworker/3:1 Tainted: GW 5.7.0-dirty #30
[ 2.564398] Hardware name: Khadas VIM3 (DT)
[ 2.568539] Workqueue: events deferred_probe_work_func
[ 2.573627] pstate: 80000005 (Nzcv daif -PAN -UAO)
[ 2.578370] pc : ethtool_check_ops+0x18/0x38
[ 2.582596] lr : register_netdevice+0x60/0x440
[ 2.586994] sp : ffff8000101d3760
[ 2.590272] x29: ffff8000101d3760 x28: ffff0000f26a0000
[ 2.595533] x27: 0000000000010009 x26: 0000000000000000
[ 2.600794] x25: ffff80001256c000 x24: ffff0000f26a0a90
[ 2.606056] x23: ffff0000f26a0d80 x22: ffff800012483140
[ 2.611317] x21: ffff8000123e9000 x20: ffff8000123e9000
[ 2.616578] x19: ffff0000f26a0000 x18: ffffffffffffffff
[ 2.621839] x17: 0000000094d2982f x16: 00000000bbcb3772
[ 2.627101] x15: ffff8000123e9848 x14: ffff0000f26a1cd0
[ 2.632362] x13: ffff0000f26a1cba x12: 0000000000000000
[ 2.637623] x11: ffff8000101d37d0 x10: ffff8000101d37d0
[ 2.642884] x9 : 00000000ffffffd8 x8 : 0000000000000204
[ 2.648146] x7 : 0000000000000204 x6 : ffff800014b00000
[ 2.653407] x5 : 0000000000000000 x4 : ffff0000f3209c80
[ 2.658668] x3 : 0000000000000000 x2 : 0000000000000000
[ 2.663929] x1 : 0000000000000000 x0 : 0000000000000000
[ 2.669191] Call trace:
1.通过addr2line定位
首先找出函数地址,在源码编译目录下的System.map中可以找到,这里错误函数是ethtool_check_ops,在System.map文件找到地址是
ffff800011ad4310 T ethtool_check_ops
加上0x18后地址就是FFFF800011AD4328。
我用的编译链是aarch64-linux-gnu-,所以addr2line前面也要加这个前缀,这里一开始有个问题,我使用addr2line的时候没有输出代码行号,只输出两个"??",后来查了资料才知道内核配置项CONFIG_DEBUG_INFO没有勾选,勾选之后重新编译,发现vmlinux这个文件变得很大了,有260M左右了,重新输入以下命令输出以下信息
linux# aarch64-linux-gnu-addr2line -e vmlinux FFFF800011AD4328
net/ethtool/common.c:346
定位问题代码在net/ethtool/common.c的346行。
2.通过gdb定位
使用 aarch64-linux-gnu-gdb vmlinux 命令进入gdb调试行,输入以下命令
(gdb) b*(0xFFFF800011AD4328)
Breakpoint 1 at 0xffff800011ad4328: file net/ethtool/common.c, line 346
可以看到两种方法定位到的代码问题行是一样的,接下去查看这行代码
int ethtool_check_ops(const struct ethtool_ops *ops)
{
if (WARN_ON(ops->set_coalesce && !ops->supported_coalesce_params)) //346
return -EINVAL;
/* NOTE: sufficiently insane drivers may swap ethtool_ops at runtime,
* the fact that ops are checked at registration time does not
* mean the ops attached to a netdev later on are sane.
*/
return 0;
}
定位到网卡驱动的ethtool中的ops这里有问题,查看驱动中ethtool_ops这个结构体中缺少supported_coalesce_params,看了其他像intel网卡驱动中的ethtool.c文件中都有这个值,于是在该结构体中添加
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
#endif
编译完成后没有错误,系统启动正常内核不再崩溃。