出现Oops消息的大部分错误时因为对NULL指针取值或者因为用了其他不正确的指针值。
Oops如何产生的解释如下:
    由于处理器使用的地址几乎都是虚拟地址,这些地址通过一个被称为“页表”的结构被映射为物理地址。当引入一个非法指针的时候,分页机制无法将该地址映射到物理地址,此时处理器就会向操作系统发出一个“页面失效(page fault)”的信号。如果地址非法“换入(page in)”缺失页面;这时,如果处理器恰好处于超级用户模式,系统就会产生一个Oops。
Oops的格式:
更加详细的解释参考下面代码,这里对输出信息做个简要介绍:
arch/arm/mm/fault.c
arch/arm/kernel/traps.c
Unable to handle kernel NULL pointer dereference at virtual address 00000000
//一段文本信息,提示表明是什么错误类型
pgd = 80004000
[00000000] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT//错误序号,中括号中蓝色
last sysfs file: 
Modules linked in://被连接进的模块
CPU: 0    Not tainted  (2.6.35.3-00054-g8deb747-dirty #1)
//发生错误的CPU序号,蓝色表示编译了10次。
PC is at mutex_lock+0xc/0x28
LR is at alc5633_reg_write+0x20/0x5c
pc : [<80375de8>]    lr : [<801ce2d0>]    psr: a0000013
sp : 9b029e50  ip : 9b029e60  fp : 9b029e5c
r10: 9b22c2d0  r9 : 9b22c2d0  r8 : 00000000
r7 : 804c0c10  r6 : 9b22c208  r5 : 00000000  r4 : 00000000
r3 : 00000001  r2 : 00000000  r1 : 00000000  r0 : 00000000
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: 90004019  DAC: 00000017
//发生错误时候CPU中各个寄存器的值,即当时CPU寄存器快照
Process swapper (pid: 1, stack limit = 0x9b0282e8)
//当前进程的名字和进程ID。但是这并不表示该进程中发生了该错误,而是表示发生错误时候,当前的进程是它。错误可能发生在内核代码、驱动程序,也可能就是这个进程的错误。
Stack: (0x9b029e50 to 0x9b02a000)
9e40:                                     9b029e7c 9b029e60 801ce2d0 80375de8
9e60: 804c0c10 00000000 9b22c200 00000000 9b029eac 9b029e80 802c043c 801ce2bc
9e80: 804e6b8c 804c0c10 804c0c44 804e6b8c 804e6b8c 00000000 00000000 00000000
9ea0: 9b029ebc 9b029eb0 801c2cac 802c0328 9b029edc 9b029ec0 801c1c48 801c2c98
9ec0: 804c0c10 804c0c44 804e6b8c 00000000 9b029efc 9b029ee0 801c1d6c 801c1b84
9ee0: 804e6b8c 9b029f00 801c1d04 00000000 9b029f24 9b029f00 801c13ac 801c1d10
9f00: 9b0068b8 9b07f8d0 804e6b8c 9b1ec5a0 804d9670 00000000 9b029f34 9b029f28
9f20: 801c1a8c 801c1364 9b029f64 9b029f38 801c0c78 801c1a78 80452a97 80023f1c
9f40: 804e6b8c 80023f1c 00000001 00000013 00000000 00000000 9b029f8c 9b029f68
9f60: 801c20a0 801c0be0 8001d024 80023f1c 00000001 00000013 00000000 00000000
9f80: 9b029f9c 9b029f90 801c313c 801c1ffc 9b029fac 9b029fa0 8001d038 801c30fc
9fa0: 9b029fdc 9b029fb0 800273b4 8001d030 800515f0 00000013 9b029fdc 9b029fc8
9fc0: 80023e64 80023f1c 800515f0 00000013 9b029ff4 9b029fe0 800084ac 8002735c
9fe0: 00000000 800083f4 00000000 9b029ff8 800515f0 80008400 ffefdb9e db31f16d
//上面是栈信息
Backtrace: 
[<80375ddc>] (mutex_lock+0x0/0x28) from [<801ce2d0>] (alc5633_reg_write+0x20/0x5c)
[<801ce2b0>] (alc5633_reg_write+0x0/0x5c) from [<802c043c>] (alc5633_codec_probe+0x120/0x224)
 r5:00000000 r4:9b22c200
[<802c031c>] (alc5633_codec_probe+0x0/0x224) from [<801c2cac>] (platform_drv_probe+0x20/0x24)
[<801c2c8c>] (platform_drv_probe+0x0/0x24) from [<801c1c48>] (driver_probe_device+0xd0/0x18c)
[<801c1b78>] (driver_probe_device+0x0/0x18c) from [<801c1d6c>] (__driver_attach+0x68/0x8c)
 r7:00000000 r6:804e6b8c r5:804c0c44 r4:804c0c10
[<801c1d04>] (__driver_attach+0x0/0x8c) from [<801c13ac>] (bus_for_each_dev+0x54/0x94)
 r7:00000000 r6:801c1d04 r5:9b029f00 r4:804e6b8c
[<801c1358>] (bus_for_each_dev+0x0/0x94) from [<801c1a8c>] (driver_attach+0x20/0x28)
 r7:00000000 r6:804d9670 r5:9b1ec5a0 r4:804e6b8c
[<801c1a6c>] (driver_attach+0x0/0x28) from [<801c0c78>] (bus_add_driver+0xa4/0x224)
[<801c0bd4>] (bus_add_driver+0x0/0x224) from [<801c20a0>] (driver_register+0xb0/0x140)
[<801c1ff0>] (driver_register+0x0/0x140) from [<801c313c>] (platform_driver_register+0x4c/0x60)
 r9:00000000 r8:00000000 r7:00000013 r6:00000001 r5:80023f1c
r4:8001d024
[<801c30f0>] (platform_driver_register+0x0/0x60) from [<8001d038>] (alc5633_init+0x14/0x1c)
[<8001d024>] (alc5633_init+0x0/0x1c) from [<800273b4>] (do_one_initcall+0x64/0x1bc)
[<80027350>] (do_one_initcall+0x0/0x1bc) from [<800084ac>] (kernel_init+0xb8/0x174)
 r7:00000013 r6:800515f0 r5:80023f1c r4:80023e64
[<800083f4>] (kernel_init+0x0/0x174) from [<800515f0>] (do_exit+0x0/0x674)
 r5:800083f4 r4:00000000
//上面是栈回溯的信息,可以从中看出调用关系。我们配置CONFIG_FRAME_POINTER这个选项也就是为了出这些信息。
Code: e89dadf0 e1a0c00d e92dd800 e24cb004 (e1903f9f) 
//出错指令附近的指令机器码,比如(出错指令在小括号内)。
---[ end trace ae0d0d75681e1941 ]---
 
 
 
上面的内核Oops就是当时调试ALC5633过程中发生的错误,正是通过Oops信息回溯发现了问题点。
明确出错原因
“Unable to handle kernel NULL pointer dereference at virtual address 00000000”可知内核因为非法地址访问出错,使用了空指针。
根据栈回溯信息找出函数调用关系。
内核崩溃时,可以从pc寄存器得知崩溃发生时的函数,出错指令。但是很多情况下是它的调入者引入的,所以找出调用关系很重要,这就是引入栈回溯的目的。
从栈回溯信息我们可以得到清晰的函数调用关系,以及最后在mutex_lock函数内部崩溃。
do_exit()
  kernel_init()
    do_one_initcall()
       alc5633_init()
         platform_driver_register()
            driver_register()
                bus_add_driver()
                   driver_attach()
                      bus_for_each_dev()
                         __driver_attach()
                           driver_probe_device()
                              platform_drv_probe()
                                 alc5633_codec_probe()
                                    alc5633_reg_write()
                                       mutex_lock()
根据PC寄存器的值确定出错位置。
PC is at mutex_lock+0xc/0x28
LR is at alc5633_reg_write+0x20/0x5c
pc : [<80375de8>]    lr : [<801ce2d0>]    psr: a0000013
sp : 9b029e50  ip : 9b029e60  fp : 9b029e5c
r10: 9b22c2d0  r9 : 9b22c2d0  r8 : 00000000
r7 : 804c0c10  r6 : 9b22c208  r5 : 00000000  r4 : 00000000
r3 : 00000001  r2 : 00000000  r1 : 00000000  r0 : 00000000
上面标示出错指令在mutex_lock偏移在0xc处的指令。pc : [<80375de8>]表示出错地址的指令为80375de8
反汇编我们的内核,采用如下指令:
./prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-objdump
 -D vmlinux > vmlinux.dis
结合反汇编我们定位到函数:
80375ddc :
80375ddc:       e1a0c00d        mov     ip, sp  
80375de0:       e92dd800        push    {fp, ip, lr, pc} 
80375de4:       e24cb004        sub     fp, ip, #4      ; 0x4   
80375de8:       e1903f9f        ldrex   r3, [r0]
80375dec:       e2433001        sub     r3, r3, #1      ; 0x1   
80375df0:       e1802f93        strex   r2, r3, [r0]
80375df4:       e1923003        orrs    r3, r2, r3
80375df8:       089da800        ldmeq   sp, {fp, sp, pc} 
80375dfc:       ebffff9f        bl      80375c80 <__mutex_lock_slowpath>
80375e00:       e89da800        ldm     sp, {fp, sp, pc} 
上面可以看到r0里面的值为0x00000000。这里知道了我们给mutex_lock传的参数为空指针。
【这里需要知道ARM函数参数传递规则,根据该规则r0存有函数传过来的第一参数,超过4个参数,要进行压栈动作了。】
下面是muetx_lock上一级的调用代码:
 96 int alc5633_reg_write(struct alc5633 *alc5633, unsigned short reg,
 97                      unsigned short val)
 98 {
 99         int ret;
100 
101         mutex_lock(&alc5633->io_lock);
102 
103         ret = alc5633_write(alc5633, reg, 2, &val);
104 
105         mutex_unlock(&alc5633->io_lock);
106 
107         return ret;
108 }
109 EXPORT_SYMBOL_GPL(alc5633_reg_write);
进而发现alc5633->io_lock为空。
在查看再上级的代码,在alc5633_codec_probe()代码如下:
779 static int alc5633_codec_probe(struct platform_device *pdev)
780 {
...
818   alc5633_reg_write(codec->control_data,ALC5633_RESET,0);
...
853 }
蓝色部分我们没有初始化具体的struct alc5633 *类型的值过来,导致了空指针的出现,定位了问题的出处,就好解决了。
 
from: http://blog.chinaunix.net/uid-27159438-id-3280213.html

ARM Linux Oops使用小结(转)的更多相关文章

  1. Arm Linux系统调用流程详细解析

    Linux系统通过向内核发出系统调用(system call)实现了用户态进程和硬件设备之间的大部分接口. 系统调用是操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的 ...

  2. ARM Linux 内核 panic 之cache 一致性 ——cci-400 cache一致互联

    ARM Linux 内核 panic 之cache 一致性 ——cci-400 cache一致互联 CCI-400 集合了互联和一致性功能,有 2 个 ACE slave 接口和 3 个 ACE-Li ...

  3. ARM Linux系统调用的原理

    转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交 ...

  4. 【Qt开发】【VS开发】【Linux开发】OpenCV、Qt-MinGw、Qt-msvc、VS2010、VS2015、Ubuntu Linux、ARM Linux中几个特别容易混淆的内容

    [Qt开发][VS开发][Linux开发]OpenCV.Qt-MinGw.Qt-msvc.VS2010.VS2015.Ubuntu Linux.ARM Linux中几个特别容易混淆的内容 标签:[Qt ...

  5. ARM Linux Qt 5.x.x 无标题栏

    /********************************************************************************* * ARM Linux Qt 5. ...

  6. Linux 常用工具小结:(5) lftp工具使用

    Linux 常用工具小结:(1) lftp工具使用. 这里会按照一些比较常用的功能列出,并举一个具体的例子逐一解释功能. 通常使用ftp过程是登陆ftp,浏览ftp内容,下载ftp文件,或者上传ftp ...

  7. 构建 ARM Linux 4.7.3 嵌入式开发环境 —— BusyBox 构建 RootFS

    上一篇我们已经成功将 ARM Linux 4.7.3 的内核利用 U-BOOT 引导了起来.但是细心的你会发现,引导到后面,系统无法启动,出现内核恐慌 (Kernel Panic). 原因是找不到文件 ...

  8. 构建 ARM Linux 4.7.3 嵌入式开发环境 —— U-BOOT 引导 Kernel

    经过若干天的反复测试,搜索.终于成功利用 Qemu 在 u-boot 下引导 ARM Linux 4.7.3 内核.如下详细解释整个构建过程. 准备环境 运行环境:Ubuntu 16.04 需要的虚拟 ...

  9. ARM Linux 3.x的设备树(Device Tree)

    http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1.     ...

随机推荐

  1. 在SpringBoot中使用热部署(DevTools)

    一.简介 有时候我们开发完SpringBoot项目后,启动运行.但是经常发现代码需要反复修改,然后修改部分内容后需要再启动....这样太费时了,热部署就是用来解决这一问题.让你修改完代码后,能自动执行 ...

  2. [svc]sed&awk过滤行及sed常用例子

    - sed过滤行 sed '2p' sed '2,5p' sed '2p;3p;4p' - awk过滤行 awk 'NR==2' awk 'NR>=2 && NR <=3' ...

  3. linux下为目录和文件设置权限

    摘:linux下为目录和文件设置权限 分类: Linux2012-05-09 03:18 7456人阅读 评论(1) 收藏 举报 linuxwordpressweb数据库serverfile linu ...

  4. 【九天教您南方cass 9.1】 06 绘制方格网

    同学们大家好,欢迎收看由老王测量上班记出品的cass9.1视频课程 我是本节课主讲老师九天. 我们讲课的教程附件也是共享的,请注意索取测量空间中. [点击索取cass教程]5元立得 (给客服说暗号:“ ...

  5. NodeJS + PhantomJS 抓取页面信息以及截图

    利用PhantomJS做网页截图经济适用,但其API较少,做其他功能就比较吃力了.例如,其自带的Web Server Mongoose最高只能同时支持10个请求,指望他能独立成为一个服务是不怎么实际的 ...

  6. npm WARN unmet dependency错误解决方法

    在MAC上安装webpack以及reactjs等其它组件时,安装太慢卡住不动,直接ctrl+c终止后,再npm install后出npm WARN unmet dependency错误,npm cac ...

  7. Java知多少(93)鼠标事件

    鼠标事件的事件源往往与容器相关,当鼠标进入容器.离开容器,或者在容器中单击鼠标.拖动鼠标时都会发生鼠标事件.java语言为处理鼠标事件提供两个接口:MouseListener,MouseMotionL ...

  8. gSOAP 初体验

    安装 由于本人使用的是 Mac OS 系统,故以 Mac OS 为例说明如何安装 gSOAP. 1)下载 gSOAP 可以在 https://sourceforge.net/projects/gsoa ...

  9. SQL SERVER EXPRESS 连接字符串

    Microsoft SQL Server Express Edition 为生成应用程序提供了一个简单的数据库解决方案.SQL Server Express Edition 支持完整的 SQL Ser ...

  10. 汉字 Unicode 编码范围

    字符集 字数 Unicode 编码 基本汉字 20902字 4E00-9FA5 基本汉字补充 38字 9FA6-9FCB 扩展A 6582字 3400-4DB5 扩展B 42711字 20000-2A ...