遇到Unable to handle kernel paging request at virtual address时Call Trace 如何查?

3,183 views
Skip to first unread message

Bryton Lee

unread,
Jul 11, 2011, 3:53:06 AM7/11/11
to linux-...@zh-kernel.org, sz...@googlegroups.com
Hi all:

我在开发中遇到如下问题 (mips CPU):
CPU 0 Unable to handle kernel paging request at virtual address 00000010,
epc =0
Oops[#1]:

Cpu
0
$ 0 : 00000000 00000000 00000000
806f22c0
$ 4 : 00000c64 00000c64 806f2000
806f2010
$ 8 : 00000001 1000003f 8052f8d8
00000001
$12 : fff7ffff 00200200 00100100
0042b018
$16 : 802c0000 bb800014 802c0000
0000000a
$20 : 802f0000 802f0000 8060ba98
80863ee8
$24 : 0000006b
2ab7b690
$28 : 80860000 80863cf8 7fb4fb08
8023d820
Hi :
000004fc
Lo :
aaaaad29
epc : 800297b8
0x800297b8
Not
tainted
ra : 8023d820
0x8023d820
Status: 10003c04
IEp
Cause :
00000008
BadVA :
00000010
PrId : 0000cd01
(<NULL>)
Process tc (pid: 3503, threadinfo=80860000, task=8060b988,
tls=00000000)
Stack : 802f0000 802f0000 8060ba98 80863ee8 8016cc88 8016cc64 7fb4fb08
8016cf0c
f3e59530 dbb09b87 00000018 bb800014 00000005 8016d148 00000000
00000001
00000000 00000000 00000000 00001f10 00000000 0000027e 0000d201
00001767
00000000 809f3780 00000000 802a0000 802efc00 0000000a 8001b53c
8060b988
807f0ec0 8024d150 8085c2a8 8003f25c 00000100 00000000 8001aecc
00000004

...
Call Trace:[<8016cc88>]
0x8016cc88
[<8016cc64>]
0x8016cc64
[<8016cf0c>]
0x8016cf0c
[<8016d148>]
0x8016d148
[<8001b53c>]
0x8001b53c
[<8003f25c>]
0x8003f25c
[<8001aecc>]
0x8001aecc
[<8003959c>]
0x8003959c
[<8001b008>]
0x8001b008
[<80000424>]
0x80000424
[<800652fc>]
0x800652fc
[<8009a5c4>]
0x8009a5c4
[<80051ae0>]
0x80051ae0
[<8019c5a8>]
0x8019c5a8
[<80018330>]
0x80018330
[<80031110>]
0x80031110
[<80018330>]
0x80018330
[<80018524>]
0x80018524
[<80001294>]
0x80001294
[<80001294>]
0x80001294


Code: 00802821 8c420248 00000000 <8c460010> 0800a5dd 00002021 00a03021
008
Disabling lock debugging due to kernel taint

我知道是某个参数传得不对,导致了非法内存访问,同时我也通过objdump -d kernel 查到 epc 是在find_task_by_vpid
函数的返回地址在br_signal_igmpproxy
但是我却在objdump -d kernel 中找不到Call Trace 中的地址, 这些地址是不是就是进程tc的地址?
另外, 我还objdump -d tc 在tc的反汇编结果中也查不到 Call Trace的地址, 根本就没有0x80开头的, 只有0x40开头的地址。
有谁能告诉我怎么查到Call Trace的调用路径吗? 非常感谢!

--
Best Regards

Bryton.Lee
_______________________________________________
Linux 内核开发中文邮件列表
Linux-...@zh-kernel.org
http://zh-kernel.org/mailman/listinfo/linux-kernel
Linux 内核开发中文社区: http://zh-kernel.org

Wick

unread,
Jul 11, 2011, 4:11:06 AM7/11/11
to sz...@googlegroups.com, linux-...@zh-kernel.org
尝试打开选项 CONFIG_KALLSYMS,会打印 oops 的函数名,堆栈等详细信息。


2011/7/11 Bryton Lee <bryto...@gmail.com>:


--
Shenzhen, CN
twitter: @izhangxc

Bryton Lee

unread,
Jul 11, 2011, 5:40:44 AM7/11/11
to Wick, sz...@googlegroups.com, linux-...@zh-kernel.org
CONFIG_KALLSYMS 这个选项要用到symbol 表吗? 如果要用到, 那就不行,
原因是我这边是在嵌入是系统上, 没有那么多的flash size。
我主要关心的是Call Trace 怎么查?

2011/7/11 Wick <izha...@gmail.com>


--
Best Regards

Bryton.Lee

Wick

unread,
Jul 11, 2011, 5:47:39 AM7/11/11
to Bryton Lee, sz...@googlegroups.com, linux-...@zh-kernel.org
2011/7/11 Bryton Lee <bryto...@gmail.com>:

> CONFIG_KALLSYMS 这个选项要用到symbol 表吗? 如果要用到, 那就不行,
> 原因是我这边是在嵌入是系统上, 没有那么多的flash size。

不需要用到,只是增加内核尺寸。这样 call trace 可以看到函数名。

> 我主要关心的是Call Trace 怎么查?

Américo Wang

unread,
Jul 12, 2011, 7:09:06 AM7/12/11
to Bryton Lee, sz...@googlegroups.com, linux-...@zh-kernel.org
2011/7/11 Bryton Lee <bryto...@gmail.com>:

> CONFIG_KALLSYMS 这个选项要用到symbol 表吗? 如果要用到, 那就不行,
> 原因是我这边是在嵌入是系统上, 没有那么多的flash size。
> 我主要关心的是Call Trace 怎么查?

如果你不能开启CONFIG_KALLSYMS,那你至少可以有System.map。

你可以参考一下sysklogd是如何查找符号表的:

char * LookupSymbol(value, sym)

unsigned long value;

struct symbol *sym;

{
auto int lp;

auto char *last;
auto char *name;

struct symbol ksym, msym;

if (!sym_array)
return((char *) 0);

last = sym_array[0].name;
ksym.offset = 0;
ksym.size = 0;
if ( value < sym_array[0].value )
return((char *) 0);

for(lp = 0; lp <= num_syms; ++lp)
{
if ( sym_array[lp].value > value )
{
ksym.offset = value - sym_array[lp-1].value;
ksym.size = sym_array[lp].value - \
sym_array[lp-1].value;
break;
}
last = sym_array[lp].name;
}

name = LookupModuleSymbol(value, &msym);

if ( ksym.offset == 0 && msym.offset == 0 )
{
return((char *) 0);
}

if ( ksym.offset == 0 || msym.offset < 0 ||
(ksym.offset > 0 && ksym.offset < msym.offset) )
{
sym->offset = ksym.offset;
sym->size = ksym.size;
return(last);
}
else
{
sym->offset = msym.offset;
sym->size = msym.size;
return(name);
}


return((char *) 0);

Reply all
Reply to author
Forward
0 new messages