37.Linux驱动调试-根据oops的栈信息,确定函数调用过程
上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html
在上章里,我们分析了oops的PC值在哪个函数出错的
本章便通过栈信息来分析函数调用过程
1.上章的oops栈信息如下图所示:
- 9fe0: 代表最初的栈顶SP寄存器位置
- 9e80:代表函数出错的SP寄存器位置
2.我们先来分析上图的栈信息,又是怎样的过程呢?
2.1内核主要是通过STMDB和LDMIA汇编命令来入栈和出栈
(STMDB和LDMIA汇编命令参考: http://www.cnblogs.com/lifexy/p/7363208.html)
内核每进入一个函数就会通过STMDB,将上个函数的内容值存入栈顶sp,然后栈顶sp-4.
当内核的某个函数出问题时,内核便通过LDMIA,将栈顶sp打印出来,然后栈顶sp+4,直到到达最初的栈顶
2.2我们以下图的3个函数为例:
若c()函数出问题后,内核就会打印b()函数的内容(0x03,LR), 打印a()函数的内容(0x02,LR),直到sp到达栈顶为止
其中lr值,便代表各个函数的调用关系
3.接下来我们便以上章的oops里的栈信息来分析
在上章里,我们找到PC值bf000078在26th_segmentfault驱动模块first_drv_open()函数下出错。
3.1先来看first_drv_open()函数,找到STMDB入栈的lr值,来确定被哪个函数调用的
如上图所示,first_drv_open()函数里,通过stmdb sp!, {r4, r5, fp, ip, lr, pc} 存入了6个值,
所以, 返回到上个函数的值lr =c008d888
在上章,我们便分析到:
内核的虚拟地址是c0004000~c03cebf4,所以c008d888位于内核的某个函数里
3.2 然后将内核进行反汇编
在内核源码的根目录下:
# arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.txt //-D:反汇编所有段 vmlinux:未压缩的内核
3.3 打开vmlinux.txt
如下图所示,搜索c008d888:
往上翻,找到c008d888位于函数chrdev_open()下:
如上图所示, chrdev_open()函数存了10个值,所以,返回到上个函数的值lr= c0089e48
3.4 继续搜索c0089e48:
往上翻,找到c0089e48位于函数__dentry_open ()下:
如上图所示, __dentry_open()函数存了10个值,所以,第二个值lr= c0089f64
3.5 继续搜索c0089f64:
往上翻,找到c0089f64位于函数nameidata_to_filp()下:
如上图所示, nameidata_to_filp函数存了6个值,所以,第二个值lr= c0089fb8
... ...(此处省略n字)
4.最终分析出,栈信息的调用过程如下:
- ret_fast_syscall()->
- sys_open()->
- do_sys_open()->
- do_filp_open()->
- nameidata_to_filp()->
- chrdev_open()->
- first_drv_open();
37.Linux驱动调试-根据oops的栈信息,确定函数调用过程的更多相关文章
- Linux驱动调试-根据oops的栈信息,确定函数调用过程
上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html 在上章里,我们分析了oops的PC值在哪个函数出错的,那如何通过栈信息来查看出错函数的整个调用 ...
- 36.Linux驱动调试-根据oops定位错误代码行
1.当驱动有误时,比如,访问的内存地址是非法的,便会打印一大串的oops出来 1.1以LED驱动为例 将open()函数里的ioremap()屏蔽掉,直接使用物理地址的GPIOF,如下图所示: 1.2 ...
- linux驱动调试--段错误之oops信息分析
linux驱动调试--段错误之oops信息分析 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id= ...
- 驱动调试-根据oops定位错误代码行
1.当驱动有误时,比如,访问的内存地址是非法的,便会打印一大串的oops出来 1.1以LED驱动为例 将open()函数里的ioremap()屏蔽掉,直接使用物理地址的GPIOF,如下图所示: 1.2 ...
- 驱动调试(四)oops确定调用树
目录 驱动调试(四)oops确定调用树 内核开启调用树 栈指针分析 原理 寄存器别名 基础解释 例子分析 找到PC地址的位置 栈分析 附录:原文的excel title: 驱动调试(四)oops确定调 ...
- 驱动调试(三)oops确定函数PC
目录 驱动调试(三)oops确定函数PC 什么是oops 流程简述 代码仓库 模块例子分析 找到PC值 判断是否属于模块 查看符号表 找到模块 反汇编模块 内核例子分析 找到PC值 判断是否属于模块 ...
- linux驱动调试记录
linux驱动调试 linux 目录 /proc 下面可以配置驱动的调试信息,比如给proc目录的自己定制的驱动的一文件设置一个变量,然后驱动程序跟了proc的参数值来配置调试级别.类似于内核调试的级 ...
- linux驱动调试--修改系统时钟终端来定位僵死问题【转】
本文转载自:http://blog.chinaunix.net/uid-20671208-id-4940381.html 原文地址:linux驱动调试--修改系统时钟终端来定位僵死问题 作者:枫露清愁 ...
- Linux内核调试方法总结之栈帧
栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...
随机推荐
- ASP.NET MVC的切片(Section)脚本(script)
在ASP.NET MVC使用切片脚本,实在是很溜. 在使用layout之后,只是视图套用_Layout之后,在视图中任一位置任一时候均可以使用切片脚本. 首先在_Layout.cshtml定一些规则: ...
- 文本框仅可接收decimal
文本框html如下: <div><label class="label">价格:</label><input id="TextP ...
- js 将一个数组插入到另一个数组的方法
JavaScript将一个数组插入到另一个数组的方法.分享给大家供大家参考.具体分析如下: 1.通过Array.prototype.push.apply方法将一个数组插入到另外一个数组,下面的代码将数 ...
- 2018 Multi-University Training Contest 5
(叹气.jpg) B.Beautiful Now 题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6351 题意:给一串长度为m的数字,k次任意交换其中 ...
- C#6.0语言规范(十三) 接口
接口定义合同.实现接口的类或结构必须遵守其合同.接口可以从多个基接口继承,并且类或结构可以实现多个接口. 接口可以包含方法,属性,事件和索引器.接口本身不为它定义的成员提供实现.接口仅指定必须由实现接 ...
- java分模块项目在idea中使用maven打包失败(ps:maven常用到的命令)
一.分模块项目打包失败 情况:项目是分模块创建的,一些公共的方法是单独的一个模块common,其他模块依赖于此模块,poom依赖已经添加了,项目可以正常运行,但使用maven打包时出现了问题:找不到依 ...
- iOS开发-自动隐藏键盘及状态栏
1.隐藏状态栏 iOS升级至7.0以后,很多API被废止,其中原有隐藏状态栏StatusBar的方法就失效了. 原有方案 [[UIApplication sharedApplication] setS ...
- mongodb postgresql mysql jsonb对比
mongodb pg mysql jsonb对比 http://erthalion.info/2017/12/21/advanced-json-benchmarks/ 使用禁用jsonb列的压缩 AL ...
- POJ 2572
#include<stdio.h> #include<iostream> #include<string> using namespace std; int mai ...
- Spring WebSocket踩坑指南
Spring WebSocket踩坑指南 本次公司项目中需要在后台与安卓App间建立一个长连接,这里采用了Spring的WebSocket,协议为Stomp. 关于Stomp协议这里就不多介绍了,网上 ...