通过JTAG对比内核启动后text/rodata段内容
关键词:vmlinux、strip、dump、_text、__end_rodata等等。
在日常的调试中,可能会在某些情况下踩到内核重要的数据,比如代码段或者rodata之类。
这种情况下,需要确认这些数据是否异常。
所谓的异常就是从DDR中读出的数据能否和vmlinux对上。
1. 准备vmlinux数据
原始的vmlinux文件,需要strip:
$(CROSS_COMPILE_PREFIX)strip vmlinux -o vmlinux_stripped
然后去掉vmlinux的0x1000头部,即一个页面。
dd if=vmlinux_stripped of=vmlinux_stripped_noheader bs= skip=
最终得到的文件vmlinux_stripped_noheader就是加载到内核中运行的可执行文件。
2. 从DDR中导出数据
连接上JTAG,然后通过dump memory将DDR中数据导出。
dump memory kernel.bin 0x8000000 0x809c7200
其中0x80000000是内核执行的起始地址,0x809c7200可以从System.map中获取,也即_end值。
3. 对比数据
3.1 确定各段数据起始和结束地址
从下图可以看出,在内核启动之后不变的数据部分是代码段(_text <--> _etext)和只读数据段(__start_rodata <--> __end_data)。
在System.map中找到如下几个关键地址:
...
T _text
...
806af4e8 T _etext
...
806b0000 R __start_rodata
...
R __end_rodata
...
在从_text到__end_rodata中间的数据,在整个运行期间是不会改变的。
获取上述符号对应地址的快捷方式:
grep -E " _text|_etext|__start_rodata|__end_rodata|__start_data_ro_after_init|__end_data_ro_after_init" System.map
但是存在一个特殊的RO_AFTER_INIT_DATA段,这部分数据在init初始化之后就不会改变。但是仍然和vmlinux是不一样的。
#ifndef RO_AFTER_INIT_DATA
#define RO_AFTER_INIT_DATA \
__start_data_ro_after_init = .; \
*(.data..ro_after_init) \
__end_data_ro_after_init = .;
#endif
得到的结果是:
8026f000 T _text----------------------------------------------dump起始地址
80629a20 T _etext---------------------------------------------text结束地址
8062a000 R __start_rodata-------------------------------------rodata起始地址
8077eac8 R __start_data_ro_after_init-------------------------init过程中可能改变区域起始地址
8077eb40 R __end_data_ro_after_init---------------------------init过程中可能改变区域结束地址。
807a6000 R __end_rodata---------------------------------------dump结束地址
3.2 从运行设备导出text和rodata段地址
从DDR中导出_text到__end_rodata之间的数据:
dump memory kernel.bin 0x8026f000 0x807a6000
3.3 从vmlinux导出源数据(text和rodata)
从stripped之后的vmlinux中截取_text到__end_rodata之间的数据:
dd if=vmlinux_stripped of=vmlinux_stripped_text_and_rodata bs= skip= count=
由于vmlinux还包含一个页面的头,之后才是加载到0x80000000地址的内容,所以需要从vmlinux多strip一个页面。所以dd skip数量为:
(_text - 0x8000000)/0x1000 + 1 = (0x8026f000 - 0x80000000)/0x1000 + 1 = 0x26f + 1= 623 + 1 = 624个页面,所以共需要strip掉624个页面。
(__end_rodata - _text)/PAGE_SIZE = (0x807a6000-0x8026f00)/0x1000 = 0x537000/0x1000 = 0x537 = 1335,所以一共需要截取1335个页面。
4. 实际比较
在BeyondCompare中进行二进制比较,找出异常点。
根据BeyondCompare结果,可以看出有那几处异常,异常起始地址和结束地址是多少。
根据BeyondComapre异常点的位置,可以倒推出vmlinux中位置,进而找到对应的符号表。
上面函数resume_userspace()异常点,也和实际现场的PC指向一致。那么问题就定位为DDR数据异常。
通过JTAG对比内核启动后text/rodata段内容的更多相关文章
- STM32F103 ucLinux开发之四(内核启动后的调试)
Stm32-uclinux启动后的调试 1. 修改__pfn_to_page使得能够启动 根据STM32F103 ucLinux开发之三(内核启动后不正常)的描述,内核无法启动是选择了平板内存模式后 ...
- springboot2.X 在项目启动后执行一段自定义代码
场景: 项目需要在项目启动后从数据库初始化一些数据进入redis , 但是没有很适合 的监听器去实现 , 监听 老是在dao初始化之前触发. 解决方法:自定义类实现 ApplicationRunner ...
- springboot启动后执行一段代码的方式
文章转载自: https://www.cnblogs.com/zuidongfeng/p/9926471.html https://blog.csdn.net/zknxx/article/detail ...
- STM32F103 ucLinux开发之三(内核启动后不正常)(完结)
STM32F103 ucLinux内核没有完全启动 从BOOT跳转到内核后,执行一长段的汇编语言,然后来到startkernel函数,开启C语言之旅. 但是内核输出不正常,如下所示: Linux ve ...
- 自定义内核启动后的Logo
1.使用图像GIMP工具 2.详细步骤如下: A.将800x480的图片导入到GIMP工具. B.选中GIMP菜单栏进行以下操作 图像 -->模式 ...
- 内核启动后,lcd显示logo失败
针对-s5pv210,但对其他平台也使用 lcd显示logo失败,若显示成功默认的logo是一只企鹅,但是串口打印“Start display and show logo”,但是LCD屏没有显示 ...
- Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html 研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内 ...
- Stm32-uclinux启动后的调试
Stm32-uclinux启动后的调试 1. 修改__pfn_to_page使得能够启动 根据STM32F103 ucLinux开发之三(内核启动后不正常)的描述,内核无法启动是选择了平板内存模式后 ...
- Linux内核启动及根文件系统载入过程
上接博文<u-boot之u-boot-2009.11启动过程分析> Linux内核启动及文件系统载入过程 当u-boot開始运行bootcmd命令,就进入Linux内核启动阶段.与u-bo ...
随机推荐
- 设计模式之单例模式(Java)
单例模式 问题 多线程操作同一对象保证对象的一致性 解决思路 只有一次实例化过程,产生一个实例化对象,并提供返回该对象的方法. 单例模式的分类 1 饿汉式 在加载类的时候就产生实例对象 public ...
- CSS入门(css简介与样式汇总、CSS的使用方式和特征、CSS基础选择器和复杂选择器、边框阴影)
一.CSS的作用 1.以统一的方式实现样式的定义 2.提高页面样式的可重用性和可维护性 3.实现了内容(HTML)和表示(CSS)的分离 HTML和CSS之间有什么关系? HTML:构建网页的结构 C ...
- ES6-promise对象的使用
Promise 的含义(摘自阮一峰ES6ru) Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一 ...
- Penetration testing“Linux install Nessus”
Ax_Download www.tenable.com/products/nessus-home,need sent email. Bx_Install su ls dpkg -i [filename ...
- gitlab忘记密码如何重置
gitlab web登入密码忘记以后可以用如下方式修改密码shell>cd /home/git/gitlabshell> su gitshell>bundle exec rails ...
- Eureka集群
Eureka集群搭建 高可用集群配置 当注册中心扛不住高并发的时候,这时候 要用集群来扛: 普通操作 我们再新建两个module microservice-eureka-server-2002 m ...
- 论文阅读:EGNet: Edge Guidance Network for Salient Object Detection
论文地址:http://openaccess.thecvf.com/content_ICCV_2019/papers/Zhao_EGNet_Edge_Guidance_Network_for_Sali ...
- 【Springboot】spring-boot-starter-redis包报错 :unknown
springboot集成redis时,引入spring-boot-starter-redis包报错,maven找不到这个资源.如下图: 我的项目中,spring boot是 用的2.0.4版本.spr ...
- [考试反思]1110csp-s模拟测试108:消遣
是套废题.T1题面错了,T2细节多而暴力>部分分,T3题目错了. T1:打表 题面应该是输出差值期望而不是答案值期望. 看到题目,果断打表. 答案就是所有值差之和除2的k次方. #include ...
- MongoDB自学------(4)MongoDB主从搭建
MongoDB复制原理 mongodb的复制至少需要两个节点.其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据. mongodb各个节点常见的搭配方式为:一主一从.一主多 ...