如何分析段错误

uuussseeennn 2010-06-16 10:41:53
我insmod一个模块的时候出错,打印出如下信息:

Unable to handle kernel NULL pointer dereference at virtual address 00000010
pgd = ceed0000
[00000010] *pgd=0ee7e031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
Modules linked in: epl sg sd_mod usb_storage scsi_mod uhci_hcd ehci_hcd usbcore moxa_dio moxa_software_id mxser_uc8400(P) nfs nfs_acl lockd sunrpc ixp400_eth ixp400
CPU: 0 Tainted: P (2.6.23.1 #986)
pc : [<c0079618>] lr : [<bf1d7ddc>] psr: 20000093
sp : cf7b3de8 ip : 00000004 fp : cf7b3e08
r10: 00008060 r9 : 00000002 r8 : 34092e16
r7 : c026e260 r6 : 000000d0 r5 : cef30000 r4 : a0000013
r3 : a0000093 r2 : 00000000 r1 : 000000d0 r0 : c026e260
Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
Control: 000039ff Table: 0eed0000 DAC: 00000015
Process insmod (pid: 917, stack limit = 0xcf7b225
Stack: (0xcf7b3de8 to 0xcf7b4000)
3de0: bf1d9180 bf1d9180 cef30000 00000024 00008000 cf7b3e3c
3e00: cf7b3e0c bf1d7ddc c00795f4 cf7b3e40 cf7b3e44 bf1d9180 0000803c 00000024
3e20: 00008000 bf1e25f0 00000002 cf7b3e70 cf7b3e6c cf7b3e40 bf1d674c bf1d7d70
3e40: cf7b3e4c c003b2c4 bf1e25f0 cf7b3e70 00000024 000249f0 bf1dd310 bf1dd308
3e60: cf7b3e88 cf7b3e70 bf1ca244 bf1d6704 c003b2c4 cf7b3eac bf1e753c cf7b3e98
3e80: cf7b3e8c bf1ca300 bf1ca214 cf7b3ecc cf7b3e9c bf1d4f60 bf1ca2fc cf7b3ebc
3ea0: cf7b3eac c003b2c4 c003af38 bf1db4b8 bf1db838 bf1db868 00000000 00000064
3ec0: cf7b3f04 cf7b3ed0 bf107184 bf1d4ea4 c0074964 bf1dc590 bf1dc590 bf1dc590
3ee0: bf1dc590 cccccccd d08d8fc0 00000019 bf1dc59c bf1dc590 cf7b3fa4 cf7b3f08
3f00: c005a778 bf10700c 00000000 cf7b2000 00000000 00000000 00000000 00000000
3f20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
3f40: 0000000c 00000018 d08e4068 cf71c030 00000000 d08d9268 d08c1000 0000000b
3f60: 00000000 000005d6 000005d6 d08d9380 00000017 00000000 00000000 00000028
3f80: beab2e83 beab2dac 00000080 c001dfc4 cf7b2000 401a3048 00000000 cf7b3fa8
3fa0: c001de20 c005a65c beab2e83 beab2dac 00900080 401aa008 00027418 00097008
3fc0: 00000028 beab2e83 beab2dac 4000b10c 00000002 0000c814 401a3048 beab2d24
3fe0: beab2cf0 beab2ce4 0000fa34 40153f00 60000010 00900080 00000000 00000000
Backtrace:
Function entered at [<c00795e8>] from [<bf1d7ddc>]
r7:00008000 r6:00000024 r5:cef30000 r4:bf1d9180
Function entered at [<bf1d7d64>] from [<bf1d674c>]
Function entered at [<bf1d66f8>] from [<bf1ca244>]
Function entered at [<bf1ca208>] from [<bf1ca300>]
r5:bf1e753c r4:cf7b3eac
Function entered at [<bf1ca2f0>] from [<bf1d4f60>]
Function entered at [<bf1d4e98>] from [<bf107184>]
r5:00000064 r4:00000000
Function entered at [<bf107000>] from [<c005a778>]
Function entered at [<c005a650>] from [<c001de20>]
Code: e121f003 e590c044 e35c0000 0a000012 (e59c500c)

从此输出的错误信息中,我如何能最快的定位到出错语句?
(用printk(...)一步步定位的方式是能找到错误点,但效率太低,我希望有更高效的找错方法)
谢谢!
...全文
349 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
操作步骤如下:
1、在编译源代码的时候加上选项-g -c,生成对应.o文件为hello.o
2、找到对应平台(你用的是ARM的就要找对应ARM的)下的objdump工具,执行objdump -j .text -Sl hello.o > 2.txt
3、打开文件2.txt,搜索上面OOPS中对应最后一行e59c500c或者0a000012 指令
Code: e121f003 e590c044 e35c0000 0a000012 (e59c500c)
4、该指令附近就有你源代码对应的行数。
uuussseeennn 2010-06-19
  • 打赏
  • 举报
回复
我用了一个很简单的hello world程序来测试kmalloc,发现还是会crash。
硬件平台:XSCALE IXP43x
软件平台:Linux2.6.23.1

代码如下:

#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */


static int __init hello_start(void)
{
int* mem;
size_t size = 64;

mem = (int*)kmalloc(size, GFP_KERNEL);

return 0;
}

static void __exit hello_end(void)
{
printk(KERN_EMERG"Goodbye Mr.\n");
}

module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");

谁有ARM平台,帮我测测,谢谢!
杨帆_8318 2010-06-19
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 uuussseeennn 的回复:]

我把大概的代码以及一些尝试写一下,希望大家帮我分析:

pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL); // 此句执行OK,ulShMemSize的值是32864
......
// 此句执行crash,sizeof(struct sShbMemTable)的值是12
psMemTableElement = kmalloc(sizeof(s……
[/Quote]

这么奇怪啊 你是在进程上下文还是中断上下文申请内存呢
yehuotaizi 2010-06-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 brookmill 的回复:]
从寄存器内容可以看到 出错地址 pc : [<c0079618>] 返回地址lr : [<bf1d7ddc>]
从Backtrace可以看到 函数入口 Function entered at [<c00795e8>] 上层函数 from [<bf1d7ddc>]

出错的语句和函数的地址都有了,通过检查符号表、反汇编,应该很快就可以定位。
[/Quote]
如这位兄弟所说,通过backtrace可以找到错误代码的地方,有时并不是当前指令错误,库函数出现问题的机率较小,但也不能完全说没有问题。大部分是因为前面传入的参数有问题导致。

这需要编译的时候把包含符号表的ELF文件保留,然后可到处符号表以及反汇编
反汇编的命令是objdump,使用-D 和-S参数可以反汇编,汇编代码和源码交替

lr寄存器是函数调用的返回地址,即上一个函数调用当前函数的地方,通过调用关系找错误代码的地方

如楼主所说printk有时并不能准确定位问题所在,字符放在缓存中没有打印出来。有时添加打印会导致编译出来的可执行代码出现大的变化,错误的地方会变化,或者没有了,以前做开发时碰到过。
zigzag_xiang 2010-06-18
  • 打赏
  • 举报
回复
学习了,顶上去!
gumbour 2010-06-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 jianmin09 的回复:]
引用 2 楼 brookmill 的回复:
c0079618 - c00795e8 = 0x30
pc是函数开始第12条指令,那么出错的指令应该是第10条,应该不难找。

由0x30怎么知道出错的指令是第10条,怎么计算?
[/Quote]
0x30 = 48
ARM9每条指令长度是4字节,PC就是第12条指令。
硬件是IXP400系列,采用ArmV5TE体系结构,五级流水线,分别为取指,译码,执行,缓存,写回
因为流水线的原因,对于数据访问指令,PC和出错指令相差2条指令。
uuussseeennn 2010-06-17
  • 打赏
  • 举报
回复
我的平台是ARM,32位系统,linux2.6.23.1
uuussseeennn 2010-06-17
  • 打赏
  • 举报
回复
我把大概的代码以及一些尝试写一下,希望大家帮我分析:

pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL); // 此句执行OK,ulShMemSize的值是32864
......
// 此句执行crash,sizeof(struct sShbMemTable)的值是12
psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL);

我做了如下尝试(主要是更改错误的那个kmalloc)都失败:
(1)改成kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL);
(2)改成psMemTableElement = kmalloc(12,GFP_KERNEL);
(3)改成psMemTableElement = kmalloc(32864,GFP_KERNEL);
(4)改成psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_ATOMIC);

但改成下面这一句就能执行通过:
psMemTableElement = kmalloc(ulShMemSize,GFP_KERNEL);
这里ulShMemSize的值是32864;但直接用32864却会crash,十分奇怪。 当然,这里多分配了这儿多空间肯定是不符合上下文环境的,这里仅供分析。(这里用ulShMemSize是因为上面红色的那句是执行通过的)

谢谢!
jianmin09 2010-06-17
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 brookmill 的回复:]
c0079618 - c00795e8 = 0x30
pc是函数开始第12条指令,那么出错的指令应该是第10条,应该不难找。
[/Quote]
由0x30怎么知道出错的指令是第10条,怎么计算?
winter_sui 2010-06-17
  • 打赏
  • 举报
回复
kmalloc有大小限制,据说只能分配128K以下大小的内存。
lisan04 2010-06-17
  • 打赏
  • 举报
回复
kmalloc出错是有可能的,不是每次分配内存都会成功,虽然出错的概率比较小。。
brookmill 2010-06-16
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 uuussseeennn 的回复:]
竟然是kmalloc出错了,有这种可能吗?

我在kmalloc的前后各加了printk,但只打印了前面的printk,后一句没打印出来
[/Quote]

kmalloc出错了……这个……可能性好像不大
用printk不是很可靠的,要打印的东西从缓冲区里输出到屏幕也是需要时间的。
有可能printk已经执行过了,但是后面的某一句出错,这时候要打印的内容还没来得及到达显示器,系统就挂了
uuussseeennn 2010-06-16
  • 打赏
  • 举报
回复
竟然是kmalloc出错了,有这种可能吗?

我在kmalloc的前后各加了printk,但只打印了前面的printk,后一句没打印出来
hfCoder 2010-06-16
  • 打赏
  • 举报
回复
mark
brookmill 2010-06-16
  • 打赏
  • 举报
回复
c0079618 - c00795e8 = 0x30
pc是函数开始第12条指令,那么出错的指令应该是第10条,应该不难找。
brookmill 2010-06-16
  • 打赏
  • 举报
回复
从寄存器内容可以看到 出错地址 pc : [<c0079618>] 返回地址lr : [<bf1d7ddc>]
从Backtrace可以看到 函数入口 Function entered at [<c00795e8>] 上层函数 from [<bf1d7ddc>]

出错的语句和函数的地址都有了,通过检查符号表、反汇编,应该很快就可以定位。

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧