根据 Oops 的 PC 定位到出错指令 / C 行
环境:Linux 5.4.31 · ARM(STM32MP157)· 故意空指针模块
pc_fault
目标:只拿到pc : [<bf1db09c>]时,如何确认是哪条汇编、对应哪行 C
目录
1. 现象(Oops 关键字段)
人为构造空指针写后,dmesg 摘要如下:
text
Unable to handle kernel NULL pointer dereference at virtual address 00000000
PC is at fault_null_write+0x24/0x2c [pc_fault]
LR is at fault_null_write+0x18/0x2c [pc_fault]
pc : [<bf1db09c>] lr : [<bf1db090>]
r3 : 12345678 r2 : 00000000 r1 : 00000001 r0 : 0000003f
Code: eb3e88f6 e3a02000 e3053678 e3413234 (e5823000)| 字段 | 含义 |
|---|---|
PC is at func+off/size [mod] | 已给出函数名、模块内偏移;优先用它 |
pc : [<addr>] | PC 绝对值;模块区常见 0xbf...... |
Code: ... (xxxxxxxx) | 括号内是触发异常的那条指令机器码 |
对应 C(节选):
c
static noinline void fault_null_write(void)
{
volatile unsigned int *p = NULL;
pr_emerg("...");
*p = 0x12345678; /* 目标:定位到这一行 */
}2. 函数名 + 偏移
Oops 若已打印:
text
PC is at fault_null_write+0x24/0x2c [pc_fault]则:
- 在与板上一致的
pc_fault.ko上反汇编; - 看
fault_null_write里偏移+0x24的那条指令; - 对照源码 /
-S输出,得到 C 行。
3. 只有裸 PC:用 kallsyms
假设只知道 pc = 0xbf1db09c:
bash
cat /proc/kallsyms | grep bf1db0示例:
text
bf1db000 t trigger_store [pc_fault]
bf1db064 t trigger_show [pc_fault]
bf1db078 t fault_null_write [pc_fault]
bf1db0a4 t fault_bad_pc [pc_fault]
...判断 PC 落在哪个符号区间,再减函数起始地址:
text
0xbf1db09c - 0xbf1db078 = 0x24
→ fault_null_write + 0x24也可用:
bash
cat /sys/module/pc_fault/sections/.text # .text 加载基址4. 定位到指令
bash
arm-buildroot-linux-gnueabihf-objdump -d pc_fault.ko > pc_fault.dis
# 或带源码行:
arm-buildroot-linux-gnueabihf-objdump -dS pc_fault.ko | lessfault_null_write 片段:
text
00000000 <fault_null_write>:
0: e92d4010 push {r4, lr}
...
14: ebfffffe bl printk
18: e3a02000 mov r2, #0
1c: e3053678 movw r3, #0x5678
20: e3413234 movt r3, #0x1234
24: e5823000 str r3, [r2] ← +0x24,出问题的指令
28: e8bd8010 pop {r4, pc}与 Oops 对齐:
- 偏移
+0x24一致; - 括号内机器码
(e5823000)与str r3, [r2]一致; - 语义:
r2=0,向地址 0 写r3,即*NULL = 0x12345678。