相关链接:
模拟系统崩溃,使用JTAG调试找到崩溃点
既然都知道怎么使用JTAG了,那就实战练练手吧~
内核添加sysrq模块
编译内核(添加sysrq功能)
make menuconfig 添加“MAGIC_SYSRQ”配置项后,执行make编译内核镜像。
编辑
运行内核(使用sysrq触发模拟系统panic)
- 关闭看门狗(防止系统重启,模拟一个系统异常卡死的环境)
devmem 0x4804c194 32 0x40000000
注:根据自己实际板卡,设置关闭看门狗
- 通过sysrq触发系统异常(echo "c" > /proc/sysrq-trigger表示产生空指针panic事件,人为导致系统崩溃)
关于sysrq的详细信息,参考:文档:Linux_Sysrq魔术键使用.note
~ # echo "c" > /proc/sysrq-trigger
SysRq : Trigger a crash
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = 8fbe0000
[00000000] *pgd=8fbe8031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1]
last sysfs file: /sys/devices/platform/omap/omap_i2c.1/i2c-1/1-0048/temp1_input
Modules linked in: pppoe pppox ppp_synctty ppp_generic slhc
CPU: 0 Not tainted (2.6.37-g7c4b7a14-dirty #1)
PC is at sysrq_handle_crash+0x24/0x30
LR is at __handle_sysrq+0xb4/0x180
pc : [<802660d4>] lr : [<802663d4>] psr: 20000093
sp : 8f247f08 ip : 8f247f18 fp : 8f247f14
r10: 60000013 r9 : 00000008 r8 : 00000000
r7 : 805d35a0 r6 : 00000063 r5 : 805ead74 r4 : 805eac74
r3 : 00000000 r2 : 00000001 r1 : 60000093 r0 : 00000063
Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c5387d Table: 8fbe0019 DAC: 00000015
Process sh (pid: 125, stack limit = 0x8f2462e8)
Stack: (0x8f247f08 to 0x8f248000)
7f00: 8f247f44 8f247f18 802663d4 802660bc 8f247f78 00000002
7f20: 802664a0 001f1e68 8f247f78 8004f808 8f246000 00000000 8f247f5c 8f247f48
7f40: 802664d8 8026632c 8fa94380 802664a0 8f247f74 8f247f60 801527f8 802664ac
7f60: 00000002 8f27b880 8f247fa4 8f247f78 80102694 801527bc 00000000 00000000
7f80: 800ffc94 00000000 00000002 001f1e68 00000001 00000004 00000000 8f247fa8
7fa0: 8004f660 8010259c 00000002 001f1e68 00000001 001f1e68 00000002 001ee328
7fc0: 00000002 001f1e68 00000001 00000004 00000000 00000002 00000001 00000000
7fe0: 001ef4c0 7efed8b0 0000c128 00008e0c 60000010 00000001 ffffffff ffffffff
Backtrace:
[<802660b0>] (sysrq_handle_crash+0x0/0x30) from [<802663d4>] (__handle_sysrq+0xb4/0x180)
[<80266320>] (__handle_sysrq+0x0/0x180) from [<802664d8>] (write_sysrq_trigger+0x38/0x40)
[<802664a0>] (write_sysrq_trigger+0x0/0x40) from [<801527f8>] (proc_reg_write+0x48/0x90)
r5:802664a0 r4:8fa94380
[<801527b0>] (proc_reg_write+0x0/0x90) from [<80102694>] (sys_write+0x104/0x140)
r5:8f27b880 r4:00000002
[<80102590>] (sys_write+0x0/0x140) from [<8004f660>] (ret_fast_syscall+0x0/0x30)
r7:00000004 r6:00000001 r5:001f1e68 r4:00000002
Code: e3a02001 e5832000 f57ff04f e3a03000 (e5c32000)
---[ end trace 08fa18d2ec21349a ]---
Kernel panic - not syncing: Fatal exception
Backtrace:
[<80053e50>] (dump_backtrace+0x0/0x130) from [<8049325c>] (dump_stack+0x18/0x1c)
r7:802660d4 r6:00000000 r5:8f247cf7 r4:80600490
[<80493244>] (dump_stack+0x0/0x1c) from [<804932d4>] (panic+0x74/0x1b0)
[<80493260>] (panic+0x0/0x1b0) from [<800542f8>] (die+0x378/0x4c0)
r3:806008cc r2:00000001 r1:000045b7 r0:80540dfc
[<80053f80>] (die+0x0/0x4c0) from [<8005787c>] (__do_kernel_fault+0x7c/0x90)
[<80057800>] (__do_kernel_fault+0x0/0x90) from [<80498b84>] (do_page_fault+0x94/0x260)
r9:00000817 r8:8f227334 r7:00000000 r6:8f227300 r5:8f247ec0
r4:00010000
[<80498af0>] (do_page_fault+0x0/0x260) from [<8003f2ec>] (do_DataAbort+0x3c/0xa0)
[<8003f2b0>] (do_DataAbort+0x0/0xa0) from [<80496a2c>] (__dabt_svc+0x4c/0x60)
Exception stack(0x8f247ec0 to 0x8f247f08)
7ec0: 00000063 60000093 00000001 00000000 805eac74 805ead74 00000063 805d35a0
7ee0: 00000000 00000008 60000013 8f247f14 8f247f18 8f247f08 802663d4 802660d4
7f00: 20000093 ffffffff
[<802660b0>] (sysrq_handle_crash+0x0/0x30) from [<802663d4>] (__handle_sysrq+0xb4/0x180)
[<80266320>] (__handle_sysrq+0x0/0x180) from [<802664d8>] (write_sysrq_trigger+0x38/0x40)
[<802664a0>] (write_sysrq_trigger+0x0/0x40) from [<801527f8>] (proc_reg_write+0x48/0x90)
r5:802664a0 r4:8fa94380
[<801527b0>] (proc_reg_write+0x0/0x90) from [<80102694>] (sys_write+0x104/0x140)
r5:8f27b880 r4:00000002
[<80102590>] (sys_write+0x0/0x140) from [<8004f660>] (ret_fast_syscall+0x0/0x30)
r7:00000004 r6:00000001 r5:001f1e68 r4:00000002
通过上面的异常崩溃打印,可以看到系统最终是在sysrq_handle_crash上停住了,对应的PC、LR地址都打印出来了。
那么,通过JTAG调试,最后获取到的PC、LR、R0~R15上的值,和上面的打印会一样吗?
使用JTAG调试(获取PC、LR寄存器对应地址)
通过之前描述的JTAG调试,获取到的PC、LR值分别为(0x801ff280、0x80493350)
和系统崩溃时打印出来的堆栈信息不一样,这是为什么呢?(后面会解释)
编辑
接着继续解析PC、LR上的地址分别代表什么含义。
反汇编内核镜像(获取每一行地址对应运行的函数)
在Linux下反汇编内核镜像(vmlinux),得到对应的反汇编文件。
反汇编相关的知识参考文档:objdump -- 反汇编uboot、uImage、vmli...
输入如下命令得到反汇编文件vmlinux.txt:
objdump -DS vmlinux > vmlinux.txt
将JTAG调试获取的PC、LR寄存器对应地址,在vmlinux反汇编文件中找到对应函数。
解析
通过JTAG获取到PC、LR等指针;
通过反汇编获取到这些指针地址对应的函数;
最后分析代码的执行流程。