这个bug搞了我整整两天,看了好多贴,调试了好多遍,终于解决了;复盘记录下。
先贴上重启打印日志。
1、重启打印日志
PC is at 0x0
LR is at devinet_ioctl+0x31c/0x5d4
pc : [<0000000000000000>] lr : [<ffffffc000507284>] pstate: 00000145
sp : ffffffc014fc3cd0
x29: ffffffc014fc3cd0 x28: 0000000000000000
x27: 00000000f475bdf4 x26: 0000000000000000
x25: 0000000000000001 x24: ffffffc014fc3d48
x23: ffffffc014fa2200 x22: ffffffc015692000
x21: ffffffc014fa2210 x20: 00000000c0a80101
x19: ffffffc0149520c0 x18: 0000000000000000
x17: 0000000000000000 x16: ffffffc000185e54
x15: 0000000000000000 x14: 0000000000000000
x13: 0000000000000000 x12: 0000000000000018
x11: 0101010101010101 x10: fefefefeff2f7161
x9 : 0000000000000000 x8 : 000000001511dda1
x7 : 0000000000000000 x6 : 000000000000003f
x5 : 0000000000000040 x4 : 0000000000000030
x3 : 0000000000000030 x2 : 0000000000000000
x1 : 0000000000000000 x0 : 00000000c0a80101
Internal error: Oops - bad mode: 0 [#1] SMP
Modules linked in: usb_led(OE) GN28L95(OE) rtsp_alg(OE) dsp_dev(OE) voip_codec(OE) kudp(OE) external_voip(OE) optical(OE) switch(OE) multicast(OE) epondrv(OE) zte_xeaspon(OE) netdriver(OE) ffe(OE) iprt(OE) tm(OE) zx_ponreg(OE) wan_bridge(OE) qos_mod(OE) bspdriver(OE)
CPU: 0 PID: 731 Comm: cspd Tainted: G OE 4.1.25 #3
Hardware name: ZTE 131G (DT)
task: ffffffc015c14340 ti: ffffffc014fc0000 task.ti: ffffffc014fc0000
PC is at 0x0
LR is at devinet_ioctl+0x31c/0x5d4
pc : [<0000000000000000>] lr : [<ffffffc000507284>] pstate: 00000145
sp : ffffffc014fc3cd0
x29: ffffffc014fc3cd0 x28: 0000000000000000
x27: 00000000f475bdf4 x26: 0000000000000000
x25: 0000000000000001 x24: ffffffc014fc3d48
x23: ffffffc014fa2200 x22: ffffffc015692000
x21: ffffffc014fa2210 x20: 00000000c0a80101
x19: ffffffc0149520c0 x18: 0000000000000000
x17: 0000000000000000 x16: ffffffc000185e54
x15: 0000000000000000 x14: 0000000000000000
x13: 0000000000000000 x12: 0000000000000018
x11: 0101010101010101 x10: fefefefeff2f7161
x9 : 0000000000000000 x8 : 000000001511dda1
x7 : 0000000000000000 x6 : 000000000000003f
x5 : 0000000000000040 x4 : 0000000000000030
x3 : 0000000000000030 x2 : 0000000000000000
x1 : 0000000000000000 x0 : 00000000c0a80101
Process cspd (pid: 731, stack limit = 0xffffffc014fc0020)
Stack: (0xffffffc014fc3cd0 to 0xffffffc014fc4000)
3cc0: 14fc3d70 ffffffc0 00508a80 ffffffc0
3ce0: 00008916 00000000 f475bdf4 00000000 0088db40 ffffffc0 f475bea8 00000000
3d00: 0088db40 ffffffc0 161bf2c0 ffffffc0 149a4000 ffffffc0 00000036 00000000
3d20: 005b0000 ffffffc0 14fc0000 ffffffc0 00898300 ffffffc0 80000000 ffffffbf
3d40: 9519f918 00000000 00307262 00000000 00000000 00000000 00000002 0101a8c0
3d60: 00000000 00000000 00000002 f475bf6c 14fc3d80 ffffffc0 004451a8 ffffffc0
3d80: 14fc3db0 ffffffc0 004475dc ffffffc0 00008916 00000000 f475bdf4 00000000
3da0: fffffdfd 00000000 00000055 00000000 14fc3e30 ffffffc0 00185f5c ffffffc0
3dc0: 00000000 00000000 149a4000 ffffffc0 149a4001 ffffffc0 f475bea8 00000000
3de0: 00008916 00000000 00000014 00000000 00000184 00000000 f6f23250 00000000
3e00: 00000000 00000000 14fc0000 ffffffc0 14fc3e20 ffffffc0 0015deac ffffffc0
3e20: 14fc3e30 ffffffc0 00185e9c ffffffc0 00000000 00000000 00083430 ffffffc0
3e40: 00400000 00000000 00000000 00000000 ffffffff ffffffff f682773c 00000000
3e60: 40070010 00000000 00000011 00000000 00000184 00000000 00000036 00000000
3e80: 14fc3e90 ffffffc0 00448ce4 ffffffc0 00000000 00000000 00083430 ffffffc0
3ea0: 00400000 00000000 00000000 00000000 ffffffff ffffffff 00083430 ffffffc0
3ec0: 00000000 00000000 161bf2c0 ffffffc0 00000014 00000000 00008916 00000000
3ee0: f475bea8 00000000 00000024 00000000 f6f23084 00000000 f475bf84 00000000
3f00: 000000c3 00000000 00000036 00000000 f475bf84 00000000 f475be58 00000000
3f20: 00000002 00000000 f475bf6c 00000000 f6f23238 00000000 f475be1c 00000000
3f40: f6f12758 00000000 00000000 00000000 00000000 00000000 00000000 00000000
3f60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
3f80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
3fa0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
3fc0: 00000000 00000000 00000000 00000000 f682773c 00000000 40070010 00000000
3fe0: 00000014 00000000 00000036 00000000 00000000 00000000 00000000 00000000
Call trace:
[< (null)>] (null)
[<ffffffc000508a80>] inet_ioctl+0x110/0x15c
[<ffffffc0004451a8>] sock_do_ioctl+0x34/0x60
[<ffffffc0004475dc>] compat_sock_ioctl+0x8a8/0x1088
[<ffffffc000185f5c>] compat_SyS_ioctl+0x108/0xec4
Code: bad PC value
add
11930:23:2---[ end trace e2975fa7062f3981 ]---
0 [route_mgr][ErKernel panic - not syncing: Fatal exception
Fatal exception
CPU: 0 PID: 731 Comm: cspd Tainted: G D OE 4.1.25 #3
Hardware name: ZTE 131G (DT)
Call trace:
[<ffffffc0000867f4>] dump_backtrace+0x0/0x100
[<ffffffc000086908>] show_stack+0x14/0x1c
[<ffffffc0005a2004>] dump_stack+0x8c/0xac
[<ffffffc0000c9138>] panic_write2+0x4c/0x60
[<ffffffc00059fc28>] panic+0xc4/0x21c
[<ffffffc000086a94>] die+0x184/0x1ac
[<ffffffc000086b04>] arm64_notify_die+0x48/0x50
[<ffffffc000086d04>] bad_mode+0x88/0x94
[<ffffffc000507284>] devinet_ioctl+0x31c/0x5d4
[<ffffffc000508a80>] inet_ioctl+0x110/0x15c
[<ffffffc0004451a8>] sock_do_ioctl+0x34/0x60
[<ffffffc0004475dc>] compat_sock_ioctl+0x8a8/0x1088
[<ffffffc000185f5c>] compat_SyS_ioctl+0x108/0xec4
ror] [route_mgr.c(2203)sreboot_info size: 4701
i_db_init_defg] si_db_qry_default_rt: nocrash_info size: 62380
default RT
11930:23:20 [routeCPU1: stopping
_mgr][Warn] [rouCPU: 1 PID: 727 Comm: cspd Tainted: G D OE 4.1.25 #3
te6_mgr.c(230)Hsardware name: ZTE 131G (DT)
_db_v6_init_d] si_db_qry_default_rt6: no default RT
11930:23:20 [route_mgr][Warn] [dbl_api.c(397)zxicDbGetView] dbAPIGetView VID(17) VN(IGD.LD1) Err(-5)
zxic_eoam_monitor_init...
Call trace:
[<ffffffc0000867f4>] dump_backtrace+0x0/0x100
[<ffffffc000086908>] show_stack+0x14/0x1c
[<ffffffc0005a2004>] dump_stack+0x8c/0xac
[<ffffffc00008a93c>] handle_IPI+0xbc/0x12c
[<ffffffc000080cb0>] gic_handle_irq+0xa8/0xc4
Exception stack(0xffffffc014f8bea0 to 0xffffffc014f8bfc0)
bea0: 00400000 00000000 00000000 00000000 ffffffff ffffffff f67d661c 00000000
bec0: 20070010 00000000 00022000 00000000 f67575f8 00000000 00000000 00000000
bee0: 000004a8 00000000 f675d168 00000000 604dc00c 00000000 604dbf7c 00000000
bf00: f67545ec 00000000 ef600c48 00000000 6047a8c8 00000000 f6754610 00000000
bf20: 00000069 00000000 f675d634 00000000 00000000 00000000 f67545c8 00000000
bf40: 001afad4 00000000 00000000 00000000 00000000 00000000 00000000 00000000
bf60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
bf80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
bfa0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Rebooting in 2 seconds..
Boot SPI NAND
bl
crpm
d3ok
SND
secure uboot
verify OK!
backup headr!!
Jump
2、解决问题
看到这些打印,我是懵逼的,主要之前汇编接触太少,gdb调试也没怎么搞过。
其实这个和我负责的模块其实不相干,但单子分到我这了,查下吧。(中间差点放弃了,哈哈哈)
2.1问题分析
通过backtrace可以看到:
PC is at 0x0
(pc是啥,后面有说明)
这是第一行的打印,很明显说这个空指针引起的。
也就是说明,内核调用到了空指针。为啥调到空指针就会重启(panic),可看文章后面的链接。
好了,问题归结到了,找到那个空指针(空指针了,还能找到?)。
2.2 问题查找
LR is at devinet_ioctl+0x31c/0x5d4
(LR后面也有说明)
这个也就是发生异常前,执行到的位置。
一、向上查找。开始我是想找到函数调用链最初的位置,但找到的是闭源文件所以放弃。
二、向下查找。
网上给出的解决方法:
0、编译选项设置,linux目录下,修改配置文件,执行:make menuconfig(UI界面配置),按照下图选择,打开调试信息。
kernel hacking—> Compile-time checks and compiler options —>
1、找到devinet_ioctl的地址,linux目录下执行
# grep -nrw "devinet_ioctl" ./System.map
21909:ffffffc000506f68 T devinet_ioctl
0X00506f68即是执行地址,加上偏移0x31c即可找到文件。
2、在linux目录下,找到编译的内核文件vmlinux,执行命令gdb vmlinux
进入gdb调试,
#(gdb) b *0x00507284
也函数名加偏移量也可以 :(gdb) b *devinet_ioctl+0x31c
PS:
1、我的操作是显示不出来文件的。原因在于出问题的不是内核,而是内核模块ko,也是为什么显示PC is at 0x0(NULL)
,但我也学习了点gdb调试,哈哈哈。
2、内核出了问题,使用上面的方法去找,但如果是内核模块的话,就需要反汇编了,将.ko文件反编译。感兴趣自行学习。因为我们的工程内核模块较多,所以我也没有进行这个操作
PS #objdump -S XX.o -g
就可以看见汇编和c语言共存的汇编中间文件了。
2.3最终解决
虽然没显示到问题错误具体地方,但是我还是找到了内核原函数
linux-lsk-v4.1.25/net/ipv4/devinet.c
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
通过和linux源码对比,将我们开发的修改之处一一分析,最终找到了问题来源。(感兴趣的小伙伴可以去看看这部分源码)
也就是在这个case下。
case SIOCSIFADDR: /* Set interface address (and family) */
这里是之前的一同事,解决一个版本广播风暴时,修改了协议栈代码,通过匹配br0,进行了策略处理,但这里并没对指针判空操作,导致其他版本系统崩溃一直重启。
图片上显示是我修改后的,对该回调函数指针进行了判空操作。之前没有判空。
实际上,我对这一部分才入手,很多说不清,汇编、反汇编、gdb,后面深入学习后,有新的认识再来补充,嘿嘿!!!
相关学习内容:
PC:
Program Counter程序计数器,用于指示当前将要执行的下一条机器指令的内存地址。在IBM PC计算机中所用的INTEL CPU中,它被称为 IP (Instruction Pointer指令指针)
LR
Link Register, 连接寄存器,在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
参考:
1、什么是 Linux “oops”?
2、linux驱动空指针引用为什么会导致内核panic?