关键词: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段内容的更多相关文章

  1. STM32F103 ucLinux开发之四(内核启动后的调试)

    Stm32-uclinux启动后的调试 1.  修改__pfn_to_page使得能够启动 根据STM32F103 ucLinux开发之三(内核启动后不正常)的描述,内核无法启动是选择了平板内存模式后 ...

  2. springboot2.X 在项目启动后执行一段自定义代码

    场景: 项目需要在项目启动后从数据库初始化一些数据进入redis , 但是没有很适合 的监听器去实现 , 监听 老是在dao初始化之前触发. 解决方法:自定义类实现 ApplicationRunner ...

  3. springboot启动后执行一段代码的方式

    文章转载自: https://www.cnblogs.com/zuidongfeng/p/9926471.html https://blog.csdn.net/zknxx/article/detail ...

  4. STM32F103 ucLinux开发之三(内核启动后不正常)(完结)

    STM32F103 ucLinux内核没有完全启动 从BOOT跳转到内核后,执行一长段的汇编语言,然后来到startkernel函数,开启C语言之旅. 但是内核输出不正常,如下所示: Linux ve ...

  5. 自定义内核启动后的Logo

    1.使用图像GIMP工具   2.详细步骤如下:   A.将800x480的图片导入到GIMP工具.   B.选中GIMP菜单栏进行以下操作     图像         -->模式       ...

  6. 内核启动后,lcd显示logo失败

    针对-s5pv210,但对其他平台也使用 lcd显示logo失败,若显示成功默认的logo是一只企鹅,但是串口打印“Start display and show logo”,但是LCD屏没有显示    ...

  7. Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html 研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内 ...

  8. Stm32-uclinux启动后的调试

    Stm32-uclinux启动后的调试 1.  修改__pfn_to_page使得能够启动 根据STM32F103 ucLinux开发之三(内核启动后不正常)的描述,内核无法启动是选择了平板内存模式后 ...

  9. Linux内核启动及根文件系统载入过程

    上接博文<u-boot之u-boot-2009.11启动过程分析> Linux内核启动及文件系统载入过程 当u-boot開始运行bootcmd命令,就进入Linux内核启动阶段.与u-bo ...

随机推荐

  1. SpringCloud断路器(Hystrix)

    一.为什么需要 Hystrix? 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC).为了保证其高可用,单个服务又必须集群部署.由于网络原因或者自身的原因,服务并不能保 ...

  2. pctfree和pctused

    pctfree 是指一个数据块保留的空间百分比,表示数据块在什么情况下可以被insert 默认是10,表示当数据块的可用空间低于10%后,就不可以被insert了,只能被用于update了 即:当使用 ...

  3. Nacos 集群部署

    关于nacos 集群部署,网上的示例往往不全或不可用,而官方的教程太简单了.官方也提供了一个 docker  + nacos 的伪集群的 部署示例.但毕竟是 伪, 不能实际生产使用. 全网就几乎就没有 ...

  4. CentOS 7 源代码安装Nginx

    本篇简要介绍CentOS 7 源代码安装Nginx. Preface # yum install epel-release -y # yum group install "Developme ...

  5. Docker安全扫描工具之DockerScan

    前言 本篇简单介绍Docker扫描工具DockerScan的安装使用.下述过程是在CentOS 7.6的虚拟机上进行的. [root@localhost ~]# cat /etc/redhat-rel ...

  6. IT兄弟连 HTML5教程 CSS3属性特效 弹性盒模型

    CSS3引入了新的盒模型——弹性盒模型,该模型决定一个盒子在其他盒子中的分布方式以及如何处理可用的空间.使用该模型,可以很轻松的创建自适应浏览器窗口的流动布局或自适应字体大小的弹性布局.弹性盒模型看起 ...

  7. Path Manipulation 路径操作

  8. python yield关键词使用总结

    python yield关键词使用总结 by:授客 QQ:1033553122 测试环境 win10 python 3.5 yield功能简介 简单来说,yield 的作用就是把一个函数变成一个 ge ...

  9. angular cli + primeNG

    目录: 1.安装  angular cli 2.创建项目 3.构建路由 4.新建组件 5.组件之间的通信 6.引入primeNG 7.修改primeNG组件样式 8.问题 -------------- ...

  10. C#&.Net干货分享-构造QRCoderHelper生成二维码图片

    不想说废话,直接源码拿去用... /// <summary>    /// 二维码管理    /// </summary>    public class QRCoderHel ...