相信自己,只有不想做的,没有做不到的。
分类: LINUX
2013-11-07 23:06:56
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
3、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
1、通过OOPS信息中PC寄存器的值可以知道出错指令的地址,通过栈回朔信息可以知道出错时的函数调用的关系,根据这两点可以很快定位错误。
2、 修改driver/video/s3c-fb.c,在s3c_fb_probe函数中int ret=0;下增加下面语句:
int *ptr = NULL;
*ptr = 0xff;
3、编译内核下载到开发板上,内核启动会出现如类似下信息:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0 Not tainted (2.6.35#6)
PC is at s3c_fb_probe+0xc/0x67c
LR is at platform_drv_probe+0x1c/0x24
pc : [
sp : cfc29f0c ip : cfc457c0 fp : 00000000
r10: 00000000 r9 : 00000000 r8 : c03ad4f8
r7 : c03a93d0 r6 : c03a93d0 r5 : c0395258 r4 : 00000000
r3 : 000000ff r2 : cfc28000 r1 : 00000000 r0 : c0395250
4、Unable to handle kernel NULL pointer dereference at virtual address 00000000
可以看出使用了空指针。找出函数调用关系:PC is at s3c_fb_probe+0xc/0x67c
,表示出错指令为 s3c_fb_probe函数中偏移为0xc的指令。pc :
[
5、结合内核源代码和反汇编代码定位问题。
arm-cortex_a8-linux-gnueabi-objdump -D vmlinux > vmlinux.dis // 文件vmlinux.dis非常大
出错地址c001abc4附近的部分汇编代码如下:
c0290a1c
c0290a1c: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
c0290a20: e3a030ff mov r3, #255
c0290a24: e3a04000 mov r4, #0
c0290a28: e5843000 str r3, [r4]
c0290a2c: e590106c ldr r1, [r0, #108]
……
对应C代码如下:
struct device *dev = &pdev->dev;
struct s3c_fb_platdata *pd;
struct s3c_fb *sfb;
struct resource *res;
int win;
int ret = 0;
int *ptr = NULL;
*ptr = 0xff;
6、对于大多数情况,从反汇编代码定位到C代码并不会如此容易,需要有较强的阅读汇编代码的能力。
7、另外一种方法是通过addr2line去定位
arm-cortex_a8-linux-gnueabi-addr2line 0xc0290a28 -e vmlinux -f