Oops 消息的产生, 例子, 定位出错位置

oops消息的产生

网上一分析oop流程的帖子, 留着以后看.

http://blog.sina.com.cn/s/blog_3e4774e30100ooey.html


oops消息的例子

1. 引用空指针

 

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
Code: 89 15 00 00 00 00 c3 90 8d 74 26 00 83 ec 0c b8 00 a6 83 d0

 

这个错误消息比较明显的,指到了空指针,位置在faulty_write 后 四个字节。

 

2. 堆栈被破坏

 

EIP: 0010:[<00000000>]
Unable to handle kernel paging request at virtual address ffffffff
printing eip:
ffffffff
Oops: 0000 [#5]
SMP
CPU: 0
EIP: 0060:[<ffffffff>] Not tainted
EFLAGS: 00010296 (2.6.6)
EIP is at 0xffffffff
eax: 0000000c ebx: ffffffff ecx: 00000000 edx: bfffda7c
esi: cf434f00 edi: ffffffff ebp: 00002000 esp: c27fff78
ds: 007b es: 007b ss: 0068
Process head (pid: 2331, threadinfo=c27fe000 task=c3226150)
Stack: ffffffff bfffda70 00002000 cf434f20 00000001 00000286 cf434f00 fffffff7
bfffda70 c27fe000 c0150612 cf434f00 bfffda70 00002000 cf434f20 00000000
00000003 00002000 c0103f8f 00000003 bfffda70 00002000 00002000 bfffda70
Call Trace:
[<c0150612>] sys_read+0x42/0x70
[<c0103f8f>] syscall_call+0x7/0xb
Code: Bad EIP value.

 

这个错误信息比较隐晦的。 说的是,找不到一个虚拟地址。 EIP一看就是个乱七八糟的值。

call trace不完整,只指示到了 sys_read。

 

造成错误的源代码是:

ssize_t faulty_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
{
    int ret;
    char stack_buf[4];
    /* Let's try a buffer overflow */
    memset(stack_buf, 0xff, 20);
    if (count > 4)
        count = 4; /* copy 4 bytes to the user */
    ret = copy_to_user(buf, stack_buf, count);
    if (!ret)
        return count;
    return ret;
}

出错的这段,是memset的时候,把stack破坏了。


利用oops消息定位出错位置

网上这两个例子不错

http://www.jishuziyuan.com/archive/myxemu/8252895.html

http://blog.chinaunix.net/uid-26318308-id-3395285.html

还有一个linus老人家自己的邮件

http://yarchive.net/comp/linux/oops_decoding.html


1. 有编译好的源代码

gdb vmlinux

(gdb)b *func+offset

or

(gdb)l *func+offset


2. 有编译好的源代码, 用objdump看

objdump -S net/core/dev.o > /tmp/dev.s

然后自己数...


3. 有编译好的源代码,用addr2line看

addr2line -e vmlinux func+offset

算好这个值,或者直接用oops上值.


4. 没有编译好的源代码,只有消息


在代码中是哪里输出的oops消息

在x86的系统中,die函数在arch/x86/kernel/dumpstack.c



你可能感兴趣的:(c,struct,user,buffer,printing)