linux驱动调试之段错误分析-根据栈信息分析函数调用过程

来源:互联网 发布:软件功能测试流程 编辑:程序博客网 时间:2024/06/05 03:54


一. 根据栈信息分析函数调用过程(如果没有回溯信息)
在函数调用中,一方面要执行,一方面要跳到返回地址(需要保存返回地址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代表全局函数
从这些信息里找到一个相近的地址, 这个地址<=0xbf000018(加载函数地址以bf0开头,内核函数地址以c0开头)
############################################################
###########################################################
3.1 根据PC确定出错位置
bf000018 属于 insmod的模块
bf000000 t first_drv_open       [first_drv]




3.2 确定它属于哪个函数
反汇编first_drv.ko






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 c3e69f00c0088fb8 c0088f40 |
                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 
阅读全文
0 0