转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id=4923529
接着上一篇来分析一下Oops的栈

s3c2440平台

关于调试源码和整个Oops信息请参考上一篇博文,这里只再次贴出关于栈的信息

Stack: (0xc3a61e30 to 0xc3a62000)
1e20: c3a61e64 c3a61e40 c00a8580 bf0d7010
1e40: c00adba8 00000000 00000000 c3b46100 c3ab84b0 c00a84b4 c3a61e8c c3a61e68
1e60: c00a3a7c c00a84c4 c3b46100 c2c0ae40 00000003 c3af0000 00000026 c3a61ed8
1e80: c3a61eac c3a61e90 c00a3d14 c00a39bc 00000000 c2c0ae40 00000000 00000000
1ea0: c3a61f64 c3a61eb0 c00b0c80 c00a3cc0 c3a61f7c c3a61ec0 c004b714 c006f8b8
1ec0: c3a61efc beb5ad9c 00000000 00000000 c3a63000 c048070c c394bc80 c34b7600
1ee0: c048077c c3a61fb0 00000000 00000101 00000001 00000000 c00441e0 c004b548
1f00: 08100875 c39568a0 c3a7ec00 0000001c 00000000 00001000 00000003 00000003
1f20: 00000000 c3b46100 00000000 c3a60000 c3a61f64 c3a61f40 c00b99b8 00000003
1f40: c3af0000 00000002 beb5ad9c ffffff9c c3a60000 00000000 c3a61f94 c3a61f68
1f60: c00a38d8 c00b0aa0 00000000 40025000 c3a61f9c 0000850c 00000000 000083e0
1f80: 00000005 c0045008 c3a61fa4 c3a61f98 c00a3988 c00a3878 00000000 c3a61fa8
1fa0: c0044e60 c00a3974 0000850c 00000000 00008590 00000002 beb5ad9c 00000001
1fc0: 0000850c 00000000 000083e0 00000005 00000000 00000000 40025000 beb5ac44
1fe0: 00000000 beb5ac28 000084b8 400efd9c 60000010 00008590 00000000 00000000

那么这一堆栈指示的是什么信息?
指示的是函数的回溯信息,我们在上一节看到了函数的回溯信息,就是函数的调用关系,栈信息不仅包含了回溯信息,
还包含了各个函数相关的寄存器,当函数切换时,会把相关的寄存器保存在自己的堆栈中,出错时,会层层打印出来。
这样会有助于我们调试,因为在内核函数中,很多数据不是在当前函数中确定的,而是由上一个函数传过来的,所以
有必要知道这么一种调用关系

下面说一下这种调用关系:

A()
{
……
B();
……
}

B()
{
……
C();
……
}

C()
{
……
}

在上面的函数调用关系中,A函数会调用B函数,B函数会调用C函数,C函数执行完之后会返回B函数,B函数执行完之后返回A函数。
那么为什么能够返回去呢?
肯定是每次发生调用切换函数时,在自己的栈中保存了一个寄存器,在函数执行完后,根据这个寄存器能够返回到调用这个函数的
代码中,这个寄存器就是lr寄存器。

每个函数都有自己的堆栈区来保存相关的寄存器,通过sp寄存器找到这个地址。如下图所示:

假如在上面的调用中,C函数出错了,会打印出相关的堆栈信息供我们分析。按什么顺序打印呢?
先打印C函数堆栈中的寄存器,在根据C堆栈中的lr寄存器找出调用它的函数,这里是B函数,然后打印出B函数
堆栈中的寄存器,同样根据B的lr寄存器找到A函数并打印,就是这样一层一层往上推的。

现在来分析栈的打印信息

首先我们知道错误处在了segment_test_open函数中,来看一下这个函数的汇编代码,确定一下它的堆栈中存了那些
寄存器
00000000 :
0: e1a0c00d mov ip, sp
4: e92dd800 push {fp, ip, lr, pc}
看到这里,由第二行知道它的堆栈中存了四个寄存器,出错时会把这个函数堆栈中这四个寄存器打印出来,就是我们看到的
前四个栈的前四个数据:
c3a61e64 c3a61e40 c00a8580 bf0d7010

这里栈地址是向上增长的,即最低地址存的是fp寄存器,fp = c3a61e64,pc = bf0d7010。如下图所示

我们根据lr寄存器来找调用它的函数,这里 lr = c00a8580,怎么根据这个地址去查找是在哪个函数呢?
首先反汇编内核(arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.dis),然后在内核的汇编代码中查找这个地址。

找到这个地址之后,向上翻看,可以看到这个地址是在 c00a84b4 :里面,也就是chrdev_open函数,就是说下一个
要打印的堆栈信息将是这个函数的。看一下这个函数的堆栈大小及寄存器

c00a84b8: e92dd8f0 push {r4, r5, r6, r7, fp, ip, lr, pc}
……
c00a84c0: e24dd008 sub sp, sp, #8 ; 0x8

这里看出chrdev_open函数的堆栈大小是 40字节,会打印出十个寄存器值(每个寄存器占4字节),lr寄存器是倒数第二个,
接下来的十个寄存器是:
c00adba8 00000000 00000000 c3b46100 c3ab84b0 c00a84b4 c3a61e8c c3a61e68 c00a3a7c c00a84c4

可以看出 lr = c00a3a7c

再去查找这个地址,知道是在 __dentry_open函数中,这个函数的反汇编:
c00a39b0: e92dddf0 push {r4, r5, r6, r7, r8, sl, fp, ip, lr, pc}

同样是十个寄存器,接下来是:
c3b46100 c2c0ae40 00000003 c3af0000 00000026 c3a61ed8 c3a61eac c3a61e90 c00a3d14 c00a39bc

lr = c00a3d14,这个地址在nameidata_to_filp函数中,然后再根据它的堆栈信息,层层网上查找,
最后会根据c0044e60地址到ret_fast_syscall 函数,再之后的地址
0000850c 00000000 00008590 …………
已经不是内核函数了,这个函数就是发生在内核调用中的最上层函数。

谁调用ret_fast_syscall函数的?
根据我们之前对系统调用的分析知道,当发生系统调用open时,会产生swi异常,陷入到内核,这个函数就是陷入内核时
首先执行的函数,然后层层调用找到我们要调用的segment_test_open函数,通过这个分析我们也可以看到系统调用open的
调用过程。

这篇博文用到了寄存器的知识,有时间再介绍

linux驱动调试--段错误之栈信息分析相关推荐

  1. linux驱动获取函数失败信息,linux驱动调试--段错误之栈信息分析

    接着上一篇来分析一下Oops的栈 s3c2440平台 关于调试源码和整个Oops信息请参考上一篇博文,这里只再次贴出关于栈的信息 Stack: (0xc3a61e30 to 0xc3a62000) 1 ...

  2. linux驱动调试--段错误之oops信息分析

    原文地址 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id=4923447 发生段错误原因就是访问 ...

  3. Linux驱动段错误,linux驱动调试--段错误之oops信息分析

    下面根据Oops信息来分析一下段错误 first_drv.c 点击(此处)折叠或打开 #include #include #include #include #include #include #in ...

  4. 37.Linux驱动调试-根据oops的栈信息,确定函数调用过程

    上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html 在上章里,我们分析了oops的PC值在哪个函数出错的 本章便通过栈信息来分析函数调用过程 1. ...

  5. linux 捕获sigsegv信息如何生成core文件,[转]Linux下的段错误产生的原因及调试方法Core Dump...

    简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址. 一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由 ...

  6. Linux环境下段错误的产生原因及调试方法小结

    From:http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基 ...

  7. [转]Linux环境下段错误的产生原因及调试方法小结

    最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的"段错误"(Segme ...

  8. [转] Linux C语言 段错误bug的调试

    原来看过一次,后来当自己有段错误的时候,才想起来这个很有用.如果不用他的方法,段错误很恶心的,不好找出来的. 下面就是原文,不过 最初出处不得而知 ======================= 复制 ...

  9. 20150430 调试分析之 根据内核报错信息栈信息分析错误

    20150430 调试分析之 根据内核报错信息栈信息分析错误 2015-04-30 Lover雪儿 还是沿用上篇文章的程序,继续研究内核报错信息 文章地址:http://www.cnblogs.com ...

最新文章

  1. 脱壳学习之加壳的概念
  2. modelsim do文件仿真
  3. Linux第六周学习总结——进程额管理和进程的创建
  4. 【secureCRT】如何在secureCRT上设置常用的快捷输出按钮栏
  5. SetRegistryKey的作用
  6. latex 数学公式_技能分享——LaTeX篇I
  7. yum时报Error: rpmdb open failed解决方法
  8. 基于JAVA+Servlet+JSP+MYSQL的人事管理系统
  9. linux内存管理(十二)-直接页面回收
  10. 乐pad平板电脑_2020年双十一高性价比平板电脑推荐(包含苹果ipad,安卓华为,微软surface)...
  11. 组织结构及权限模型设计
  12. 2018尚硅谷大数据视频_韩顺平_Linux视频教程
  13. 如何在word里插入矢量图
  14. 解决win10新建文本文档内容可以打开但显示图标不对的问题
  15. linux重装系统步骤 包含raid【主要针对服务器重装】
  16. 思维方式-《成功与运气》书中的精髓:成功到底是靠天赋、努力,还是运气?
  17. postman全方位讲解(有空看下)
  18. STM32F103_study50_The punctual atoms(STM32 General timer basic principle )
  19. React类式组件基础内容补充
  20. 小白学电脑计算机的组成,零基础的电脑小白学电脑

热门文章

  1. 数据库中数据的独立性解释
  2. DBD::mysql的安装
  3. 面试集锦|浪潮集团技术一面
  4. 每周分享五个 PyCharm 使用技巧(三)
  5. 分椰子c语言csdn,水手分椰子——迭代法、递归解题
  6. Dijkstra 路径规划算法在二维仿真环境中的应用 -- Python代码实现
  7. ngnix配置cgi和fastcgi
  8. 直击招聘程序员面试笔试C语言深度解析,直击招聘 程序员面试笔试C++语言深度解析(直击招聘) pdf epub mobi txt 下载...
  9. diag()函数功能
  10. 艾司博讯:拼多多价格竞争力不足怎么办