Linux 核心發生嚴重錯誤(如空指標解參考)時,會輸出 Oops 訊息,包含當下 CPU 狀態、堆疊回溯、錯誤碼與 Tainted 旗標,是驅動開發除錯的關鍵線索。本文以故意製造 NULL pointer dereference 的核心模塊為例,示範如何結合 objdump 反組譯精確定位錯誤行,並完整解讀 Oops 各欄位含義。
/* oops_demo.c */
#include
#include
static int __init oops_init(void) {
int *p = 0;
*p = 1; // 故意解參考 NULL 指標
return 0;
}
static void __exit oops_exit(void) {}
module_init(oops_init);
module_exit(oops_exit);
MODULE_LICENSE("GPL");
make
insmod oops_demo.ko
# 系統輸出 Oops 訊息至 dmesg / 主控台
[ 100.243737] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 100.244985] IP: [] oops_init+0x5/0x11 [oops_demo]
[ 100.262266] *pde = 00000000
[ 100.288395] Oops: 0002 [#1] SMP
[ 100.305468] last sysfs file: /sys/devices/virtual/sound/timer/uevent
[ 100.325955] Modules linked in: oops_demo(+) ...
[ 100.472178] Pid: 1586, comm: insmod Not tainted (2.6.32-21-generic #32-Ubuntu) VMware Virtual Platform
[ 100.540018] EIP: 0060:[] EFLAGS: 00010246 CPU: 0
[ 100.562844] EIP is at oops_init+0x5/0x11 [oops_demo]
[ 100.584351] EAX: 00000000 EBX: fffffffc ECX: f82cf040 EDX: 00000001
[ 100.609358] ESI: f82cf040 EDI: 00000000 EBP: f1b9ff5c ESP: f1b9ff5c
[ 100.631467] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 100.657664] Process insmod (pid: 1586, ti=f1b9e000 task=f137b340 task.ti=f1b9e000)
[ 100.706083] Stack:
[ 100.731783] f1b9ff88 c0101131 f82cf040 c076d240 fffffffc f82cf040 0072cff4 f82d2000
[ 100.759324] <0> fffffffc f82cf040 0072cff4 f1b9ffac c0182340 f19638f8 f137b340 f19638c0
[ 100.811396] <0> 00000004 09cc9018 09cc9018 00020000 f1b9e000 c01033ec 09cc9018 00015324
[ 100.891922] Call Trace:
[ 100.916257] [] ? do_one_initcall+0x31/0x190
[ 100.943670] [] ? oops_init+0x0/0x11 [oops_demo]
[ 100.970905] [] ? sys_init_module+0xb0/0x210
[ 100.995542] [] ? syscall_call+0x7/0xb
[ 101.024087] Code: 05 00 00 00 00 01 00 00 00 5d c3 00 00 00 00 00 00 00 00 00 00
[ 101.079592] EIP: [] oops_init+0x5/0x11 [oops_demo] SS:ESP 0068:f1b9ff5c
[ 101.134682] CR2: 0000000000000000
[ 101.158929] ---[ end trace e294b69a66d752cb ]---
| 欄位 | 含義 | 本例數值 |
|---|---|---|
| BUG 行 | 錯誤類型描述 | kernel NULL pointer dereference at (null) |
| IP / EIP | 發生錯誤的指令指標 | oops_init+0x5 (模塊基址 f82d2000 + 0x5) |
| Oops: 0002 | 錯誤碼 (十六進位) | bit1=1 (Write)、bit2=0 (Kernel mode) → 核心態寫入導致頁面保護錯誤 |
| [#1] | 此 CPU 發生第 1 次 Oops | #1 |
| Call Trace | 函數呼叫堆疊回溯 | insmod → sys_init_module → do_one_initcall → oops_init |
| Code | 錯誤指令附近機器碼 | c7 05 00 00 00 00 01 00 00 00 → movl $0x1, 0x0 |
| CR2 | 導致頁面錯誤的線性位址 | 0x0 (NULL) |
| Tainted | 核心污染狀態 | Not tainted (GPL 模組、正常載入、無強制卸載、無 MCE) |
objdump -S oops_demo.o
# 輸出片段:
oops_demo.o: file format elf32-i386
Disassembly of section .init.text:
00000000 :
0: 55 push %ebp
1: 31 c0 xor %eax,%eax
3: 89 e5 mov %esp,%ebp
5: c7 05 00 00 00 00 01 movl $0x1,0x0 ← offset 0x5
c: 00 00 00
f: 5d pop %ebp
10: c3 ret
oops_init+0x5,對應反組譯 offset 0x5 的 movl $0x1, 0x0。*p = 1; (第 7 行)。
/* arch/x86/mm/fault.c */
* error_code:
* bit 0 = 0: 頁面不存在 (P=0) 1: 保護錯誤 (P=1, 權限不符)
* bit 1 = 0: 讀取 1: 寫入
* bit 2 = 0: 核心模式 1: 用戶模式
* bit 3 = 0: 資料存取 1: 指令擷取
* bit 4 = 1: 保留位被設定 (PSE/ NX 等)
本例 0x2 = 0b0010 → 保護錯誤、寫入、核心模式、資料存取。
| 位置 | 字元 | 含義 |
|---|---|---|
| 1 | G / P | 所有模組 GPL 相容 / 有專有模組 |
| 2 | F / _ | 曾用 insmod -f 強制載入 / 正常 |
| 3 | S / _ | SMP 核心跑在未認證硬體 / 正常 |
| 4 | R / _ | 曾用 rmmod -f 強制卸載 / 正常 |
| 5 | M / _ | CPU 回報 Machine Check Exception / 無 |
| 6 | B / _ | 頁面釋放發現壞頁面引用 / 無 |
| 7 | U / _ | 用戶主動要求設定 Tainted / 無 |
| 8 | D / _ | 核心近期曾死機 (Oops/BUG) / 無 |
| 9 | A / _ | ACPI 表被覆寫 / 無 |
| 10 | W / _ | 核心曾發出警告 / 無 |
| 11 | C / _ | 載入 staging 驅動 / 無 |
| 12 | I / _ | 核心繞過平台韌體嚴重 Bug / 無 |
核心開發者收到 Oops 時,優先查看 Tainted 判斷環境乾淨度;自行除錯驅動可暫時忽略。
dmesg 完整保留,可直接分析。vga=791 等高解析度參數,增加畫面顯示行數。console=ttyS0,115200 將輸出導向宿主機記錄。crashkernel= 保留記憶體,Oops 觸發時自動轉儲 vmcore,事後用 crash 或 gdb 分析。MODULE_LICENSE("GPL"),避免 Tainted 干擾核心開發者判斷。IP/EIP + objdump -S 定位原始碼行,再結合 Call Trace 理解呼叫脈絡。kdump,確保死機現場可事後複盤。企業級防火牆部署 Apache 反向代理:多內站統一對外發布全流程
Linux Root 密碼重置與破解方法總彙整 (Grub/單用戶/救援模式)
Linux 下 LAMP/LNMP 一鍵安裝包(含 WDCP 面板)
Linux 與 Windows 檔案互傳實戰:FTP 伺服器 架設與指令操作全指南
su 切換用戶報「Permission denied」根因:根目錄遺失執行權限
Fail2Ban 實戰部署:阻擋 SSH 暴力破解的自動化防火牆整合指南
微軟延長 Windows Vista 與 Windows 7 生命週期
VMware Workstation 安裝 Ubuntu Server 完整指南:網絡 NAT 模式、SSH 遠程與常用服務部署