一. 根據棧信息分析函數調用過程(如果沒有回溯信息)
在函數調用中,一方面要執行,一方面要跳到返回地址(需要保存返回地址lr(在棧里面保存))
# ./firstdrvtest on
Unable to handle kernel paging request at virtual address 56000050
pgd = c3e78000
[56000050] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in: first_drv
CPU: 0 Not tainted (2.6.22.6 #48)
PC is at first_drv_open+0x18/0x3c [first_drv]
LR is at chrdev_open+0x14c/0x164
pc : [<bf000018>] lr : [<c008c888>] psr: a0000013
############################################################
###########################################################
看System.map確定內核的函數的地址范圍:c0004000~c03265a4
先看看加載的驅動程序的函數的地址范圍
cat /proc/kallsyms (內核函數、加載的函數的地址)(k代表內核,all代表所有,syms代表符號(函數))
把輸出信息放到一個文件里面去,好分析
里面的t代表靜態函數,T代表全局函數
############################################################
###########################################################
3.1 根據PC確定出錯位置
00000000 <first_drv_open>:
0: e1a0c00d mov ip, sp
4: e92dd800 stmdb sp!, {fp, ip, lr, pc} //先把寄存器保存到棧里面
8: e24cb004 sub fp, ip, #4; 0x4
c: e59f1024 ldr r1, [pc, #36]; 38 <__mod_vermagic5>
10: e3a00000 mov r0, #0; 0x0
14: e5912000 ldr r2, [r1]
18: e5923000 ldr r3, [r2]//出錯地方,r2指向的是56000050
first_drv_open函數棧信息:出錯時把棧打印出來,從下往上打印
由於sp指向的棧空間存儲fp, ip, lr, pc
相應的寄存器可以參考<Linux應用開發完全手冊>的71頁。
下面部分是 first_drv_open函數的棧,往上是調用者的棧
sp : c3e69e88 ip : c3e69e98 fp : c3e69e94
r10: 00000000 r9 : c3e68000 r8 : c0490620
r7 : 00000000 r6 : 00000000 r5 : c3e320a0 r4 : c06a8300
r3 : bf000000 r2 : 56000050 r1 : bf000964 r0 : 00000000
Flags: NzCv IRQs on FIQs on Mode SVC_32 Segment user
Control: c000717f Table: 33e78000 DAC: 00000015
Process firstdrvtest (pid: 752, stack limit = 0xc3e68258)
Stack: (0xc3e69e88 to 0xc3e6a000)
//c008c888 是返回地址, first_drv_open函數調用完后就會返回到他的調用者的地址lr,因為是c00開頭的,所以是內核的函數,反匯編內核,在反匯編文件里面搜索地址c008c888就可以知道是哪一個函數,往前面查找到 chrdev_open函數。后面00000000 c0490620 是調用者的棧,9個寄存器共占據9格,
9e80: c3e69ebc c3e69e98 c008c888 bf000010 | 00000000 c0490620
first_drv_open'sp (占4格) lr chrdev_open'sp(占9格)
這里把sp-4(可能需要存局部變量),也就是共10格(每格4個字節)這個解析是棧指針向下移動
9ea0: c3e320a0 c008c73c c0465e20 c3e36cb4 c3e69ee4 c3e69ec0 c0088e48c008c74c |
lr
9ec0: c0490620 c3e69f04 00000003 ffffff9c c002b044 c06e0000 c3e69efc c3e69ee8
__dentry_open'sp(共10個寄存器)后面沒有對sp的加減
9ee0: c0088f64 c0088d58 |00000000 00000002 c3e69f68 c3e69f00c0088fb8c0088f40 |
lr nameidata_to_filp'sp lr
占5個寄存器,這里sp再減4,共占據6個4字節
9f00: c3e69f04 c3e36cb4 c0465e20 00000000 00000000 c3e79000 00000101 00000001
do_filp_open'sp
這里有sp的運算,而sp-84,84/4=21,加寄存器共占27個字
9f20: 00000000 c3e68000 c04c1468 c04c1460 ffffffe8 c06e0000 c3e69f68 c3e69f48
9f40: c008916c c009ec70 00000003 00000000 c0490620 00000002 be94eee0 c3e69f94
9f60: c3e69f6c c00892f4 c0088f88| 00008520 be94eed4 0000860c 00008670 00000005
lr do_sys_open'sp
共占據11個
9f80: c002b044 4013365c c3e69fa4 c3e69f98 c00893a8 c00892b0 |00000000 c3e69fa8
lr sys_open'sp
9fa0: c002aea0 c0089394| be94eed4 0000860c 00008720 00000002 be94eee0 00000001
lr ret_fast_syscall'sp
9fc0: be94eed4 0000860c 00008670 00000002 00008520 00000000 4013365c be94eea8
9fe0: 00000000 be94ee84 0000266c 400c98e0 60000010 00008720 00000000 00000000
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。