一个oops问题的调试

    技术2022-05-18  16

    参考文档

    kernel document里oops-trace.txt

    LDD 第四章

     

    打印信息中会告诉你死在哪个函数

    然后去查找pc 寄存器指针位置(即下面的EIP)

    Unable to handle kernel NULL pointer dereference at virtual address 00000000 printing eip: d083a064 Oops: 0002 [#1] SMP CPU: 0 EIP: 0060:[<d083a064>] Not tainted EFLAGS: 00010246 (2.6.6) EIP is at faulty_write+0x4/0x10 [faulty] eax: 00000000 ebx: 00000000 ecx: 00000000 edx: 00000000 esi: cf8b2460 edi: cf8b2480 ebp: 00000005 esp: c31c5f74 ds: 007b es: 007b ss: 0068 Process bash (pid: 2086, threadinfo=c31c4000 task=cfa0a6c0) Stack: c0150558 cf8b2460 080e9408 00000005 cf8b2480 00000000 cf8b2460 cf8b2460 fffffff7 080e9408 c31c4000 c0150682 cf8b2460 080e9408 00000005 cf8b2480 00000000 00000001 00000005 c0103f8f 00000001 080e9408 00000005 00000005 Call Trace: [<c0150558>] vfs_write+0xb8/0x130 [<c0150682>] sys_write+0x42/0x70 [<c0103f8f>] syscall_call+0x7/0xb

    注:示例是随便写的

     

    Oops: 0002 [#1]

    其中0002代表错误码 (读错误、发生在内核空间),#1代表Oops发生次数。

    * error_code: *       bit 0 == 0 means no page found, 1 means protection fault *       bit 1 == 0 means read, 1 means write *       bit 2 == 0 means kernel, 1 means user-mode

    首先arm-linux-objdump -d vmlinux > dump

    查找指针所对应的指令

    c0279f18:    ea000032     b    c0279fe8 <put_cmsg+0x104> c0279f1c:    e288700c     add    r7, r8, #12 c0279f20:    e1530007     cmp    r3, r7 c0279f24:    31a07003     movcc    r7, r3 c0279f28:    e1a0300d     mov    r3, sp c0279f2c:    35900018     ldrcc    r0, [r0, #24] c0279f30:    e3c36d7f     bic    r6, r3, #8128    ; 0x1fc0 c0279f34:    e3c6603f     bic    r6, r6, #63    ; 0x3f c0279f38:    33800008     orrcc    r0, r0, #8 c0279f3c:    35840018     strcc    r0, [r4, #24] c0279f40:    e58d200c     str    r2, [sp, #12]

     

    然后去找出错函数的文件

    arm-linux-objdump -S sysfs.o > dump2

    查找具体出错的位置

    static inline void list_del(struct list_head *entry) {     __list_del(entry->prev, entry->next);     entry->next = LIST_POISON1;   34:    e59f307c     ldr    r3, [pc, #124]    ; b8 <sysfs_release+0xb8>   38:    e1530007     str    r3, [r4, #56]    ; 0x38     entry->prev = LIST_POISON2;   3c:    e59f3078     ldr    r3, [pc, #120]    ; bc <sysfs_release+0xbc>   40:    e584303c     str    r3, [r4, #60]    ; 0x3c     unsigned long tmp;     int result;     smp_mb();

     

    其实前面的log中  sys_write+0x42/0x70 这种表示从sys_write函数开始往下0x42行

    然后发现是一个指针问题

    ktype的指针不对

    但这个指针指向的是一个全局变量device_ktype

     

    后来发现添加设备时 全局变量加了个__initdata  结果挂载系统是这个全局变量会被释放掉。

     

    而出现这个问题是因为这段代码是我copy的, 看来还是要自己打字写代码,少copy。

     

    这个问题还有个更简单点的办法

    http://elinux.org/Main_Page

    pc : [<c01b063c>] lr : [<c01b0640>] psr: a0000013 # arm-none-linux-gnueabi-addr2line -f -e vmlinux c01b063c msmfb_suspend /home/gnutoo/embedded/htcdream/SHR/kernel/linux/drivers/video/msm/msm_fb.c:485 参数也可用这个-C -f -s -e

    重新编译内核时,选上kernel hacking--->compile the kernel with debug info

     ---->kernel debugging ?

    system_map中查到free_block地址0x40097ac0+0x78得到0x40097B38

    arm-gdb vmlinux

    (gdb) l *0x40097B38

    在命令行上键入命令:l(小写的L * at cif_cam_isr_in8920+0x5c // l表示查找,*表示通配符

    CONFIG_FRAME_POINTER ?

    Code: e89dadf0 e1a0c00d e92dd800 e24cb004 (e1903f9f)  //出错指令附近的指令机器码,比如(出错指令在小括号内)。

     __do_kernel_fault(mm, addr, fsr, regs);

    fsr 是CPSR

     http://www.bsdmap.com/UNIX_html/ARM/apcsintro.html

    http://www.360doc.com/content/11/1022/20/1317564_158274805.shtml


    最新回复(0)