欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

编译完成后没有错误,系统启动正常内核不再崩溃。