當內核出現類似用戶空間的 Segmentation fault 時,oops會被打印到控制檯和寫入內核log緩衝區。
下面來製造一個oops,程序如下:
#include <linux/init.h>
#include <linux/module.h>
static int __init test_init(void)
{
char *tmp = NULL;
*tmp = 0x1;
return 0;
}
static void __exit test_exit(void)
{
return;
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL v2");
如上,在 test_init() 函數中存在空指針錯誤,在加載模塊時,內核的oops打印如下:
[ 28.142547] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 28.151618] pgd = ed8b8000
[ 28.154632] [00000000] *pgd=7bd08835
[ 28.158643] Internal error: Oops: 817 [#1] PREEMPT SMP ARM
[ 28.164753] Modules linked in: test(+) 8189fs
[ 28.192879] CPU: 0 PID: 1429 Comm: insmod Not tainted 4.9.118 #2034
[ 28.199855] Hardware name: arm
[ 28.203736] task: ee2167c0 task.stack: ee1ee000
[ 28.208785] PC is at test_init+0x8/0x10 [test]
[ 28.213737] LR is at do_one_initcall+0x140/0x174
[ 28.218880] pc : [<bf1df008>] lr : [<c0101afc>] psr: 60000013
[ 28.218880] sp : ee1efdf8 ip : 00000000 fp : c017be2c
[ 28.231673] r10: ed8a3aa4 r9 : 00000001 r8 : ed8a3a80
[ 28.237489] r7 : 00000000 r6 : ffffe000 r5 : c0a0400c r4 : bf1df000
[ 28.244760] r3 : 00000001 r2 : 00040976 r1 : bf1df000 r0 : 00000000
[ 28.252031] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
[ 28.259979] Control: 10c5387d Table: 6d8b806a DAC: 00000051
[ 28.266377]
[ 28.266377] LR: 0xc0101a7c:
[ 28.271129] 1a7c e5983004 e1570003 0a000003 e59f1090 e28d0014 eb072890 e5887004 e10f3000
[ 28.280278] 1a9c e3130080 0a000004 e3a02040 e59f1074 e28d0014 eb072a56 f1080080 e5dd3014
[ 28.289432] 1abc e3530000 0a000006 e28d3014 e59f2058 e58d3000 e3001319 e1a03004 e59f004c
[ 28.298582] 1adc eb005a2b e59d2054 e1a00006 e5953000 e1520003 0a000003 eb005996 e12fff34
[ 28.307733] 1afc e1a06000 eaffffd8 e28dd05c e8bd83f0 c0a0400c ffffe000 c0b06000 c07c22cf
[ 28.316885] 1b1c c07c22e4 c07c2311 c07c2327 c07c233c c07c20f0 e5900184 e3500000 012fff1e
[ 28.326034] 1b3c e1a03001 e92d4010 e5912004 e1a01000 e5930000 eb0729fc e16f0f10 e1a002a0
[ 28.335189] 1b5c e8bd8010 e92d40f0 e24dd04c e59f6350 e3a02009 e59f134c e1a04000 e5963000
[ 28.344343]
[ 28.344343] SP: 0xee1efd78:
[ 28.349095] fd78 00000005 00190002 024000c0 c01bef54 ef0021c0 efda8880 ed844040 bf1df008
[ 28.358249] fd98 60000013 ffffffff ee1efddc c010b938 00000000 bf1df000 00040976 00000001
[ 28.367399] fdb8 bf1df000 c0a0400c ffffe000 00000000 ed8a3a80 00000001 ed8a3aa4 c017be2c
[ 28.376548] fdd8 00000000 ee1efdf8 c0101afc bf1df008 60000013 ffffffff 00000051 bf000000
[ 28.385700] fdf8 00000001 00190018 ed844040 c01c2bd8 c07dda5e c0941470 ef0021c0 60000013
[ 28.394852] fe18 024000c0 c0184764 c0184764 00000000 c017be2c c01c1b5c 00000000 ef0021c0
[ 28.403996] fe38 024000c0 ee1ee000 ee1efe48 c01c1d80 c0b110ec 00040976 ee1eff44 bf1dd040
[ 28.413146] fe58 ee1eff44 ed844040 bf1dd088 ed8a3a80 00000001 c01847a0 bf1dd040 00000001
[ 28.422303]
[ 28.422303] FP: 0xc017bdac:
[ 28.427058] bdac e3500000 1a000019 e7d43006 e353003d 1a000016 e2866001 e0844006 e1a00004
[ 28.436208] bdcc e8bd81f0 e3520001 e2455001 e1a03000 9a000010 e5d31000 e1a02005 e2830001
[ 28.445361] bdec e3510000 1afffff6 e1a04003 e2833001 e5d41000 e3510000 1affffe2 e3520001
[ 28.454509] be0c e2455001 9a000003 e1a02005 eafffff5 e1a03004 eaffffee e3a04000 eaffffe6
[ 28.463658] be2c e92d4010 e59d1008 e592000c e59d2010 e0801001 e1a00003 eb051d25 e59d0010
[ 28.472811] be4c e8bd8010 e5913024 e1a00002 e59f1008 e5932178 e2422001 ea054e60 c07d2a33
[ 28.481965] be6c e5913024 e1a00002 e59f1004 e59320f8 ea054e5a c07cb14b e5913024 e1a00002
[ 28.491116] be8c e59f1004 e59320e4 ea054e54 c07cb14b e1a03002 e59f1008 e5902020 e1a00003
[ 28.500267]
[ 28.500267] R5: 0xc0a03f8c:
[ 28.505020] 3f8c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.514176] 3fac 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.523328] 3fcc 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.532480] 3fec 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000001
[ 28.541630] 400c 00040976 00000009 001fb0d6 00000000 00000012 ffffffff 00000000 00000000
[ 28.550781] 402c 0000000f 0000000f 0000000f 0000000f 00000000 00000000 ef00e640 ef00f840
[ 28.559932] 404c ef00e840 ef007940 ef00f640 ef00ea40 ef00f440 00000001 00000001 00000001
[ 28.569081] 406c 00000000 00000028 00989680 00000000 00000000 00004e20 00000000 00000000
[ 28.578225]
[ 28.578225] R6: 0xffffdf80:
[ 28.582976] df80 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.592127] dfa0 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.601279] dfc0 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.610425] dfe0 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.619574] e000 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.628715] e020 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.637866] e040 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.647017] e060 ******** ******** ******** ******** ******** ******** ******** ********
[ 28.656165]
[ 28.656165] R8: 0xed8a3a00:
[ 28.660917] 3a00 c01d061c c0106ea0 00000000 00000000 00000000 00000000 00000000 00000002
[ 28.670068] 3a20 00000551 ffff8ebb 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a
[ 28.679226] 3a40 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc
[ 28.688380] 3a60 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc
[ 28.697535] 3a80 ed8a2f40 00000001 ee2a2180 00000124 00000024 bf1dd004 c017be2c 00000000
[ 28.706686] 3aa0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.715834] 3ac0 cccccccc ed8a3bc0 c017e45c c01c1c34 c017e45c c017ebdc c0106ea0 00000000
[ 28.724982] 3ae0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.734135]
[ 28.734135] R10: 0xed8a3a24:
[ 28.738983] 3a24 ffff8ebb 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a cccccccc
[ 28.748136] 3a44 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc
[ 28.757287] 3a64 cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc cccccccc ed8a2f40
[ 28.766436] 3a84 00000001 ee2a2180 00000124 00000024 bf1dd004 c017be2c 00000000 00000000
[ 28.775585] 3aa4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 cccccccc
[ 28.784741] 3ac4 ed8a3bc0 c017e45c c01c1c34 c017e45c c017ebdc c0106ea0 00000000 00000000
[ 28.793892] 3ae4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.803046] 3b04 00000000 00000000 00000000 00000595 ffff95ce c027f4ec c027f4ec c027f558
[ 28.812201] Process insmod (pid: 1429, stack limit = 0xee1ee210)
[ 28.818890] Stack: (0xee1efdf8 to 0xee1f0000)
[ 28.823739] fde0: 00000001 00190018
[ 28.832852] fe00: ed844040 c01c2bd8 c07dda5e c0941470 ef0021c0 60000013 024000c0 c0184764
[ 28.841967] fe20: c0184764 00000000 c017be2c c01c1b5c 00000000 ef0021c0 024000c0 ee1ee000
[ 28.851077] fe40: ee1efe48 c01c1d80 c0b110ec 00040976 ee1eff44 bf1dd040 ee1eff44 ed844040
[ 28.860190] fe60: bf1dd088 ed8a3a80 00000001 c01847a0 bf1dd040 00000001 bf1dd040 ee1eff44
[ 28.869302] fe80: 00000001 c017e4fc bf1dd04c 00007fff bf1dd040 c017bf74 00000000 f1928000
[ 28.878414] fea0: c017be9c c0701c6c f1928a44 bf1dd1ac b6ef00e0 00000003 ed836f40 ffffffff
[ 28.887527] fec0: 00000000 00000000 00000000 00000000 00000000 00000000 6e72656b 00006c65
[ 28.896640] fee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 28.905751] ff00: 00000000 00000000 00000000 00000000 00000000 00040976 00000000 00000a94
[ 28.914861] ff20: 00023c14 00000000 f1928a94 ee1ee000 b6ef00e0 00000051 00000000 c017ebdc
[ 28.923975] ff40: 00000000 f1928000 00000a94 f1928724 f192863c f192854c 000001c0 00000200
[ 28.933088] ff60: 00000000 00000000 00000000 00000300 00000014 00000015 0000000d 00000000
[ 28.942202] ff80: 0000000b 00000000 00000000 00000000 00000004 00000080 c0107088 ee1ee000
[ 28.951312] ffa0: 00000000 c0106ea0 00000000 00000000 00023180 00000a94 b6ef00e0 00005d01
[ 28.960426] ffc0: 00000000 00000000 00000004 00000080 00000a94 00000000 00000020 00000000
[ 28.969535] ffe0: be9ccc3c be9ccc20 00011adc b6f3a110 60000010 00023180 5a5a5a5a 5a5a5a5a
[ 28.978668] [<bf1df008>] (test_init [test]) from [<c0101afc>] (do_one_initcall+0x140/0x174)
[ 28.987978] [<c0101afc>] (do_one_initcall) from [<c01847a0>] (do_init_module+0x54/0x37c)
[ 28.996998] [<c01847a0>] (do_init_module) from [<c017e4fc>] (load_module+0x15ec/0x1bb0)
[ 29.005920] [<c017e4fc>] (load_module) from [<c017ebdc>] (SyS_init_module+0x11c/0x128)
[ 29.014747] [<c017ebdc>] (SyS_init_module) from [<c0106ea0>] (ret_fast_syscall+0x0/0x48)
[ 29.023762] Code: bad PC value
[ 29.027207] ---[ end trace b80675877b6d72fb ]---
oops信息解讀
- 一段文本描述信息
比如類似“Unable to handle kernel NULL pointer dereference at virtual address 00000000”的信息,它說明了發生的是哪類錯誤。 - Oops 信息的序號
比如是第 1 次、第 2 次等。這些信息與下面類似,中括號內的數據表示序號。Internal error: Oops: 805 [#1] - 內核中加載的模塊名稱,也可能沒有,以下面字樣開頭。
Modules linked in: - 發生錯誤的 CPU 的序號,對於單處理器的系統,序號爲 0,比如:
CPU: 0
Not tainted (2.6.22.6 #36) - 發生錯誤時 CPU 的各個寄存器值。
- 當前進程的名字及進程 ID,比如:
Process swapper (pid: 1, stack limit = 0xc0480258)
這並不是說發生錯誤的是這個進程,而是表示發生錯誤時,當前進程是它。錯誤可能發生在內核、驅動程序,也可能就是這個進程的錯誤。 - 棧信息。
- 棧回溯信息,可以從中看出函數調用關係,形式如下:
Backtrace:
[] (s3c2410fb_probe+0x0/0x560) from [] (platform_drv_probe+0x20/0x24)
… - 出錯指令附近的指令的機器碼,比如(出錯指令在小括號裏)
Code: e24cb004 e24dd010 e59f34e0 e3a07000 (e5873000)
oops的log分析如下:
- 明確出錯原因:“Unable to handle kernel NULL pointer dereference at virtual address 00000000”。可知是由於非法地址訪問出錯導致的,使用了空指針。
- “Internal error: Oops: 817 [#1] PREEMPT SMP ARM”,oops信息的序號,比如是第 1 次、第 2 次等。這些信息與下面類似,中括號內的數據表示序號。
- 此時內核加載的模塊名稱,“Modules linked in:”,也是有可能沒有的。
- 發生錯誤的CPU序號等信息:“CPU: 0 PID: 1429 Comm: insmod Not tainted 4.9.118 #2034”。
- 發生錯誤時各寄存器的值。
- 棧信息等。
oops信息分析
明確出錯原因
由出錯信息“Unable to handle kernel NULL pointer dereference at virtual address 00000000”可知內核是因爲非法地址訪問出錯,使用了空指針
根據棧回溯信息找出函數調用關係
從內核崩潰時打印的pc寄存器可以知道發生崩潰時正在運行的函數。
[ 28.208785] PC is at test_init+0x8/0x10 [test]
[ 28.213737] LR is at do_one_initcall+0x140/0x174
[ 28.218880] pc : [<bf1df008>] lr : [<c0101afc>] psr: 60000013
[ 28.218880] sp : ee1efdf8 ip : 00000000 fp : c017be2c
[ 28.231673] r10: ed8a3aa4 r9 : 00000001 r8 : ed8a3a80
[ 28.237489] r7 : 00000000 r6 : ffffe000 r5 : c0a0400c r4 : bf1df000
[ 28.244760] r3 : 00000001 r2 : 00040976 r1 : bf1df000 r0 : 00000000
...
[ 28.978668] [<bf1df008>] (test_init [test]) from [<c0101afc>] (do_one_initcall+0x140/0x174)
上面表示,do_one_initcall() 調用了 test_init() 函數,而前面的“bf1df008”是 test_init() 函數首地址偏移爲0的地址,這個函數的大小爲 0x10;而後面的“c0101afc”是 do_one_initcall() 函數首地址偏移爲0的地址,這個函數的大小爲 0x174。
結合內核源代碼和反彙編代碼定位問題
生成內核的反彙編代碼 test.dis
arm-linux-objdump -dS test.ko > test.dis
附上部分調試工具命令:
arm-linux-readelf
- 查看是否包含debug信息: arm-linux-readelf –S hello | grep debug
- 查看依賴庫: arm-linux-readelf –d hello
arm-linux-nm
- 查看依賴函數: arm-linux-nm –D hello
- 查看函數大小: arm-linux-nm –s –r hello | head -10
- 查看函數名和行號: arm-linux-nm –l vmlinux
arm-linux-addr2line
- 查看地址對應源碼: arm-linux-addr2line –f –e vmlinux {address}
arm-linux-objdump
- 反彙編(包含源碼): arm-linux-objdump –dS hello
- 查看header信息: arm-linux-objdump –x hello