Oops信息及栈回溯_第1页
Oops信息及栈回溯_第2页
Oops信息及栈回溯_第3页
Oops信息及栈回溯_第4页
Oops信息及栈回溯_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Oops信息及栈回溯(2011-10-2510:16)标签:信息分类:linuxOops信息来源及格式Oops这个单词含义为“惊讶”,当内核出错时(比如访问非法地址)打印出来的信息被称为Oops信息。Oops信息包含以下几部分内容:一段文本描述信息。比如类似“UnabletohandlekernelNULLpointerdereferenceatvirtualaddress00000000的信息,他说明了发生的是哪类错误。Oops信息的序号。比如是第几次等。这些信息与下面类似,括号内的数据表示序号。Internalerror:Oops:806#1内核中加载的模块名称,也可能没有,以下面字样开头

2、。Moduleslinkedin:发生错误的CPU的序号,对于单处理器系统,序号为0,如:CPU:0Nottainted(#36)发生错误时CPU的各个寄存器值。当前进程的名字及进程ID,比如:Processswapper(pid:1,stacklimit=0 xc0480258)这并不是说发生错误的是这个进程,而是表示发生错误时,当前进程是它。错误可能发生在内核代码、驱动程序,也可能就是这个进程的错误。栈信息。栈回溯信息,可以从中看出函数调用关系,形式如下:Backtrace:(s3c2410fb_probe+0 x0/0 x560)from(platform_drv_pro

3、be+0 x20/0 x24)出错指令附近的指令机器码,比如(出错指令在小括号内):Code:e24cb004e24dd010e59f34e0e3a07000(e5873000)2.配置内核使Oops信息的栈回溯信息更直观Linux2.26.32自身具备的调试功能,可以使打印出的Oops信息更直观。通过Oops信息中PC寄存器的值可以知道出错指令的地址,通过栈回溯信息可以知道出错时的函数调用关系,根据这两点可以很快定位错误。要让内核出错时能够打印栈回溯信息,编译内核时要增力口“-fno-omit-frame-pointer选项,这可以通过配置CONFIG_FRAME_POINTER来实现。查看

4、内核目录下的配置文件.config,确保CONFIG_FRAME_POINTER已经被定义,如果没有,执行“makemenuconfig”命令重新配置内核。CONFIG_FRAME_POINTER有可能被其他配置项目自动选上。3使用Oops信息调试内核的实例(1)获得Oops信息本小节故意修改LCD驱动程序drivers/video/s3c2410fb.c,加入错误代码:在be函数的开头增加下面两条代码:int*ptest=NULL;*ptest=0 x1234;重新编译内核,启动后会出错并打印出如下Oops信息:UnabletohandlekernelNULLpoi

5、nterdereferenceatvirtualaddress00000000pgd=c000400000000000*pgd=00000000Internalerror:Oops:805#1lastsysfsfile:Moduleslinkedin:CPU:0Nottainted(2.6.32#24)PCisats3c2410fb_probe+0 xc/0 x18LRisatplatform_drv_probe+0 x18/0 x1cpc:lr:psr:a0000013sp:c3823f30ip:c3842e7cfp:00000000r10:00000000r9:00000000r8:c04

6、45008r7:c38a0840r6:c0440d18r5:c042d178r4:00000000r3:00001234r2:00000000r1:00000000r0:c042d170Flags:NzCvIRQsonFIQsonModeSVC_32ISAARMSegmentkernelControl:c000717fTable:30004000DAC:00000017Processswapper(pid:1,stacklimit=0 xc3822270)Stack:(0 xc3823f30to0 xc3824000)3f20:00000000c01d2e7cc0440d18c042d1783

7、f40:0000000cc042d178c042d1acc0440d18c38a0840c01d306800000000c01d300c3f60:c0440d18c01d24e8c3804938c38473300000000000000000c0440d18c01d1d483f80:c03a1506c03a150600000001c0022dd400000000c0440d18c0018f84000000003fa0:00000000c01d3334c0022dd40000000000000000c0018f8400000000c0018f903fc0:c0022dd4c002e37cc001

8、8f84c03c5ab3c0457880c0022fc8c0022dd4000000003fe0:000000000000000000000000c00083f800000000c002fe540000000000000000(s3c2410fb_probe+0 xc/0 x18)from(platform_drv_probe+0 x18/0 x1c)(platform_drv_probe+0 x18/0 x1c)from(driver_probe_device+0 x148/0 x2d8)(driver_probe_device+0 x148/0 x2d8)from(_driver_atta

9、ch+0 x5c/0 x7c)(_driver_attach+0 x5c/0 x7c)from(bus_for_each_dev+0 x48/0 x78)(bus_for_each_dev+0 x48/0 x78)from(bus_add_driver+0 xe0/0 x288)(bus_add_driver+0 xe0/0 x288)from(driver_register+0 xa4/0 x130)(driver_register+0 xa4/0 x130)from(s3c2410fb_init+0 xc/0 x28)(s3c2410fb_init+0 xc/0 x28)from(do_o

10、ne_initcall+0 x5c/0 x1b4)(do_one_initcall+0 x5c/0 x1b4)from(kernel_init+0 x94/0 x10c)(kernel_init+0 x94/0 x10c)from(kernel_thread_exit+0 x0/0 x8)Code:eafffe97e3a02000e59f3008e1a01002(e5823000)endtraceda227214a82491b7swapperusedgreateststackdepth:5792bytesleftKernelpanic-notsyncing:Attemptedtokill(un

11、wind_backtrace+0 x0/0 x150)from(panic+0 x40/0 x120).1.2.3.(panic+0 x40/0 x120)from(do_exit+0 x64/0 x5f4)(do_exit+0 x64/0 x5f4)from(die+0 x15c/0 x180)(die+0 x15c/0 x180)from(_do_kernel_fault+0 x64/0 x74)(_do_kernel_fault+0 x64/0 x74)from

12、(do_page_fault+0 x1b8/0 x1cc)(do_page_fault+0 x1b8/0 x1cc)from(do_DataAbort+0 x34/0 x94)(do_DataAbort+0 x34/0 x94)from(_dabt_svc+0 x40/0 x60)Exceptionstack(0 xc3823ee8to0 xc3823f30)3ee0:c042d17000000000000000000000123400000000c042d1783f00:c0440d18c38a0840c0445008000000000000000000000000c3842e7cc3823

13、f303f20:c01d3f88c0018f78a0000013ffffffff(_dabt_svc+0 x40/0 x60)from(s3c2410fb_probe+0 xc/0 x18)(s3c2410fb_probe+0 xc/0 x18)from(platform_drv_probe+0 x18/0 x1c)(platform_drv_probe+0 x18/0 x1c)from(driver_probe_device+0 x148/0 x2d8)(driver_probe_device+0 x148/0 x2d8)from(_driver_attach+0 x5c/0 x7c)(_d

14、river_attach+0 x5c/0 x7c)from(bus_for_each_dev+0 x48/0 x78)(bus_for_each_dev+0 x48/0 x78)from(bus_add_driver+0 xe0/0 x288)(bus_add_driver+0 xe0/0 x288)from(driver_register+0 xa4/0 x130)(driver_register+0 xa4/0 x130)from(s3c2410fb_init+0 xc/0 x28)(s3c2410fb_init+0 xc/0 x28)from(do_one_initcall+0 x5c/

15、0 x1b4)(do_one_initcall+0 x5c/0 x1b4)from(kernel_init+0 x94/0 x10c)(kernel_init+0 x94/0 x10c)from(kernel_thread_exit+0 x0/0 x8)(2)分析Oops信息确出错原因。由出错信息“UnabletohandlekernelNULLpointerdereferenceatvirtualaddress00000000”可知内核是因为非法地址访问出错,使用了空指针。根据栈回溯信息找出函数调用关系。内核崩溃时,可以从pc寄存器得知崩溃发生时的函数、出错指令。但是很多情况下,错误有可能是

16、它的调用者引入的,所以找出函数的调用关系也很重要。部分栈回溯信息如下:(s3c2410fb_probe+0 xc/0 x18)from(platform_drv_probe+0 x18/0 x1c)这行信息分为两部分,表示后面的platform_drv_probe函数调用了前面的s3c2410fb_probe函数。前半部含义为:“c0018f78”是s3c2410fb_probe函数首地址偏移0 xc的地址,这个函数大小为0 x18。后半部含义为:“c01d3f88”是platform_drv_probe函数首地址偏移0 x18的地址,这个函数大小为0 x1c。另外,后半部的“”表示s3c24

17、10fb_probe执行后的返回地址。对于类似下面的栈回溯信息,其中是r8r4表示driver_probe_device函数刚被调用时这些寄存器的值。从上面的栈回溯信息可以知道内核出错时的函数调用关系如下最后在s3c2410fb_probe函数内部崩溃。do_exit-kernel_init-do_one_initcall-s3c2410fb_init-driver_register-bus_add_driver-bus_for_each_dev-_driver_attach-driver_probe_device-platform_drv_probe-s3c2410fb_probe根据pc寄

18、存器的值确定出错位置。上述Oops信息中出错时的寄存器值如下:PCisats3c2410fb_probe+0 xc/0 x18LRisatplatform_drv_probe+0 x18/0 x1cpc:lr:psr:a0000013sp:c3823f30ip:c3842e7cfp:00000000r10:00000000r9:00000000r8:c0445008r7:c38a0840r6:c0440d18r5:c042d178r4:00000000r3:00001234r2:00000000r1:00000000r0:c042d170PCisats3c2410fb_probe+0 xc/0

19、 xl8表示出错指令为s3c2410fb_probe函数中偏移为Oxc的指令。pc:表示出错指令的地址为cOO18f78(十六进制)。结合内核源代码和反汇编代码定位问题。先生成内核的反汇编代码vmlinux.dis,执行以下命令:$cd/Documents/myTest/kernel/linux-2.6.32$arm-linux-objdump-Dvmlinuxvmlinux.dis出错地址cOO18f78附近的部分汇编代码如下:cOO18f64:cOO18f64:e3aO1OO1movr1,#1;Ox1cOO18f68:eafffe97bcOO189cc4.cOO18f6c:cOO18f6c

20、:e3aO2OOOmovr2,#O;OxOcOO18f7O:e59f3OO8ldrr3,pc,#8;cOO18f8OcOO18f74:e1aO1OO2movr1,r2cOO18f78:e5823OOOstrr3,r2=出错指令cOO18f7c:eafffe92bcOO189cccOO18f8O:OOOO1234.wordOxOOOO123412.cOO18f84:cOO18f84:e92d4O1Opushr4,lrcOO18f88:e59fOO14ldrrO,pc,#2O;cOO18fa4cOO18f8c:ebO6edO6blcO1d43accOO18f9O:e35OOOOOcmprO,#O;

21、OxOc0018f94:18bd8010popner4,pcc0018f98:e59f0008ldrr0,pc,#8;c0018fa8c0018f9c:e8bd4010popr4,lrc0018fa0:ea06ed01bc01d43acc0018fa4:c0440d04.word0 xc0440d04出错指令为“strr3,r2”,它把r3寄存器的值放到内存中,内存地址为r2寄存器的值。根据Oops信息中的寄存器值可知:r3为00001234,r2为0。0地址不可访问,所以出错。staticint_inits3c2410fb_probe(structplatform_device*pdev)/

22、addforkernelpanic-beginint*ptest=NULL;*ptest=0 x1234;/addforkernelpanic-endreturns3c24xxfb_probe(pdev,DRV_S3C2410);结合反汇编代码,很容易知道是“*ptest=0 x1234;”导致错误,其中的ptest为空。对于大多数情况,从反汇编代码定位到C代码并不会如此容易,这需要较强的阅读汇编程序的能力。通过栈回溯信息知道函数的调用关系,这已经可以帮助定位很多问题了。4.使用Oops的栈信息手工进行栈回溯前面说过,从Oops信息的pc寄存器值可知得知崩溃发生时的函数、出错指令。但是错误有可

23、能是它的调用者引入的,所以还要找出函数的调用关系。由于内核配置了CONFIG_FRAME_POINTER,当出现Oops信息时,会打印栈回溯信息。如果内核没有配置CONFIG_FRAME_POINTER,这时可以自己分析栈信息,找到函数的调用关系。栈的作用一个程序包含代码段、数据段、BSS段、堆、栈;其中数据段用来中存储初始值不为0的全局数据,BSS段用来存储初始值为0的全局数据,堆用于动态内存分配,栈用于实现函数调用、存储局部变量。被调用函数在执行之前,它会将一些寄存器的值保存在栈中,其中包括返回地址寄存器lr。如果知道了所保存的lr寄存的值,那么就可以知道它的调用者是谁。在栈信息中,一个函

24、数一个函数地往上找出所有保存的lr值,就可以知道各个调用函数,这就是栈回溯的原理。栈回溯实例分析仍以前面的LCD驱动程序为例,使用上面的Oops信息的栈信息进行分析,栈信息如下:Stack:(0 xc3823f30to0 xc3824000)3f20:00000000c01d2e7cc0440d18c042d1783f40:0000000cc042d178c042d1acc0440d18c38a0840c01d306800000000c01d300c3f60:c0440d18c01d24e8c3804938c38473300000000000000000c0440d18c01d1d483f80

25、:c03a1506c03a150600000001c0022dd400000000c0440d18c0018f84000000003fa0:00000000c01d3334c0022dd40000000000000000c0018f8400000000c0018f903fc0:c0022dd4c002e37cc0018f84c03c5ab3c0457880c0022fc8c0022dd4000000003fe0:000000000000000000000000c00083f800000000c002fe540000000000000000根据pc寄存器值找到第一个函数,确定它的栈大小,确定调用

26、函数。从Oops信息1.PCisats3c2410fb_probe+0 xc/0 x18LRisatplatform_drv_probe+0 x18/0 x1cpc:lr:psr:a0000013sp:c3823f30ip:c3842e7cfp:00000000r10:00000000r9:00000000r8:c0445008r7:c38a0840r6:c0440d18r5:c042d178r4:00000000r3:00001234r2:00000000r1:00000000r0:c042d170可知pc值为cOO18f7&使用它在内核反汇编程序vmlinux.dis中可以知道它位于s3c

27、2410fb_probe函数内。c0018f6c:c0018f6c:e3a02000movr2,#0;0 x0c0018f70:e59f3008ldrr3,pc,#8;c0018f80c0018f74:e1a01002movr1,r2c0018f78:e5823000strr3,r2=出错指令c0018f7c:eafffe92bc00189ccc0018f80:00001234.word0 x00001234lr存放的是函数返回值地址,为c01d3f88,根据这个地址,搜索内核反汇编程序vmlinux.dis,可知它位于:c01d3f70:c01d3f70:e92d4010pushr4,lrc01d3f74:e1a03000movr3,r0c01d3f78:e5933044ldrr3,r3,#68c01d3f7c:e2400008subr0,r0,#8;0 x8c01d3f80:e1a0e00fmovlr,pcc01d3f84:e513f014ldrpc,r3,#-20c01d3f88:e8bd8010popr4,pc也就是说,函数s3c2410fb_p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论