Linux Vmlinux反汇编操作和 oops stack 回朔分析

2023-10-27

1. Linux Vmlinux反汇编操作和代码分析

1.1 对vmlinx反汇编

arm-linux-gnueabi-objdump -d vmlinux > debug.s

1.2 debug.s代码段分析

vmlinux:     file format elf32-littlearm
Disassembly of section .head.text:
内核地址      汇编对应的机器码   汇编指令        
c0008000 <stext>:   
//ARM在链接脚本里面,指定了内核的入口是stext
//在vmlinux.lds指定了ENTRY(stext) ,然后. = 0xC0000000 +0x00008000;
// .head.text :...,所以执行地址是内核地址0xc0008000
c0008000:       e10f9000        mrs r9, CPSR
c0008004:       e229901a        eor r9, r9, #26
c0008008:       e319001f        tst r9, #31
c000800c:       e3c9901f        bic r9, r9, #31
c0008010:       e38990d3        orr r9, r9, #211    ; 0xd3
c0008014:       1a000004        bne c000802c <stext+0x2c>
c0008018:       e3899c01        orr r9, r9, #256    ; 0x100
c000801c:       e28fe00c        add lr, pc, #12

下面这段是函数代码段,当我们把一个函数编译进内核(有系统)的时候,系统加载器会自动帮我们分配执行地址,如下面的c0008084,当内核调用这个函数的时候,根据函数名称就能找到对应的地址并执行

c0008084 <__create_page_tables>:
c0008084:   e2884901    add r4, r8, #16384  ; 0x4000
c0008088:   e1a00004    mov r0, r4
c000808c:   e3a03000    mov r3, #0
c0008090:   e2806901    add r6, r0, #16384  ; 0x4000
c0008094:   e4803004    str r3, [r0], #4
c0008098:   e4803004    str r3, [r0], #4
c000809c:   e4803004    str r3, [r0], #4

说明:那么我们得到这个反汇编的文件后有什么用处呢?下面结合oops栈回溯来介绍

2. oops 栈回朔分析

2.1 oops是什么?

这里,我们要理解一下oops是什么?oops语义上类似于惊讶,也类似于拟声词,像”哎呦”,所以对于程序来说,就如“哎呦,出错了!”,然后把出错的地址,各个寄存器的值等等打印出来。 首先,我们根据内核打印信息的段错误信息来分析,例子如下:

Unable to handle kernel paging request at virtual address 56000050
//内核使用56000050来访问时发生了错误
pgd = c3eb0000
[56000050] *pgd=00000000
Internal error: Oops: 5 [#1]    
//5表示错误代码,#1表示这个错误发生一次
Modules linked in: first_drv
// 在哪个模块出错
CPU: 0    Not tainted  (2.6.22.6 #1)
// 发生错误的CPU序号
   PC is at first_drv_open+0x18(该指令的偏移)/0x3c(该函数的总大小) [first_drv]
// 出错函函数,PC就是发生错误的指令的地址 
LR is at chrdev_open+0x14c/0x164
// LR寄存器的值,错误函数的栈返回地址
pc = 0xbf000018
// 出错时各个寄存器的值
pc : [<bf000018>]    lr : [<c008d888>]    psr: a0000013
sp : c3c7be88  ip : c3c7be98  fp : c3c7be94
r10: 00000000  r9 : c3c7a000  r8 : c049abc0
r7 : 00000000  r6 : 00000000  r5 : c3e740c0  r4 : c06d41e0
r3 : bf000000   r2 : 56000050  r1 : bf000964  r0 : 00000000
// 执行这条导致错误的指令时各个寄存器的值
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: c000717f  Table: 33eb0000  DAC: 00000015
Process firstdrvtest (pid: 777, stack limit = 0xc3c7a258)
//发生错误时当前进程的名称是firstdrvtest
栈
Stack: (0xc3c7be88 to 0xc3c7c000)
be80:            c3c7bebc c3c7be98 c008d888 bf000010 00000000 c049abc0
bea0:c3e740c0 c008d73c c0474e20 c3e766a8 c3c7bee4 c3c7bec0 c0089e48 c008d74c
bec0: c049abc0 c3c7bf04 00000003 ffffff9c c002c044 c3d10000 c3c7befc c3c7bee8
bee0: c0089f64 c0089d58 00000000 00000002 c3c7bf68 c3c7bf00 c0089fb8 c0089f40
bf00: c3c7bf04 c3e766a8 c0474e20 00000000 00000000 c3eb1000 00000101 00000001
bf20: 00000000 c3c7a000 c04a7468 c04a7460 ffffffe8 c3d10000 c3c7bf68 c3c7bf48
bf40: c008a16c c009fc70 00000003 00000000 c049abc0 00000002 bec1fee0 c3c7bf94
bf60: c3c7bf6c c008a2f4 c0089f88 00008520 bec1fed4 0000860c 00008670 00000005
bf80: c002c044 4013365c c3c7bfa4 c3c7bf98 c008a3a8 c008a2b0 00000000 c3c7bfa8
bfa0: c002bea0 c008a394 bec1fed4 0000860c 00008720 00000002 bec1fee0 00000001
bfc0: bec1fed4 0000860c 00008670 00000002 00008520 00000000 4013365c bec1fea8
bfe0: 00000000 bec1fe84 0000266c 400c98e0 60000010 00008720 00000000 00000000

Backtrace: (回溯) // 在内核里面,选中FRAME_POINTER ,出错时才会打印出这些消息

[<bf000000>](first_drv_open+0x0/0x3c[first_drv])from[<c008d888>]    (chrdev_open+0x14c/0x164)
[<c008d73c>] (chrdev_open+0x0/0x164) from [<c0089e48>] (__dentry_open+0x100/0x1e8)
r8:c3e766a8 r7:c0474e20 r6:c008d73c r5:c3e740c0 r4:c049abc0
[<c0089d48>] (__dentry_open+0x0/0x1e8) from [<c0089f64>] (nameidata_to_filp+0x34/0x48)
[<c0089f30>] (nameidata_to_filp+0x0/0x48) from [<c0089fb8>] (do_filp_open+0x40/0x48)
r4:00000002
[<c0089f78>] (do_filp_open+0x0/0x48) from [<c008a2f4>] (do_sys_open+0x54/0xe4)
r5:bec1fee0 r4:00000002
[<c008a2a0>] (do_sys_open+0x0/0xe4) from [<c008a3a8>] (sys_open+0x24/0x28)
[<c008a384>] (sys_open+0x0/0x28) from [<c002bea0>] (ret_fast_syscall+0x0/0x2c)
Code: e24cb004 e59f1024 e3a00000 e5912000 (e5923000)
Segmentation fault  

2.2 oops调试步骤

根据上面的回朔信息,我们可以如下调试: (1) 根据pc值,查看出错的地址是在内核还是在insmod 加载的驱动在内核里面,执行 cat System.map 查看内核的地址范围

(2) 查看内核函数,加载函数的地址 cat /proc/kallsyms > xx.text 这个xx.text里面,现在就有各个函数里面的地址根据pc值,找出一个相近的地址,这个地址<= pc值,找到 bf000000 t first_drv_open [first_drv] 出错的就是first_drv_open函数,t代是static函数

(3)反汇编

如果是在insmod加载的驱动的错误 arm-linux-objdump -D xxx.ko > xxx.dis 如果是在内核中的错误 arm-linux-objdump -D vmlinux > vmlinux.s

(4)在反汇编文件(.s)里面搜索first_drv_open

如果是内核,在内核的.dis里面查找pc值,例如

c014e6a8 <first_drv_open>:
c014e6a8:       e1a0c00d        mov     ip, sp 
c014e6ac:       e92dd800        stmdb   sp!, {fp, ip, lr, pc}
c014e6b0:       e24cb004        sub     fp, ip, #4      ; 0x4
c014e6b4:       e59f1024        ldr     r1, [pc, #36]   ;               c014e6e0 <.text+0x1276e0> 
c014e6b8:       e3a00000        mov     r0, #0  ; 0x0
c014e6bc:       e5912000        ldr     r2, [r1] 
c014e6c0:  e5923000   ldr  r3, [r2] // 在此出错 r2=56000050

如果是insmod加载的函数,找个first_drv_open,然后确定是哪个寄存器的值出错了。first_drv.s文件insmod后

00000000 <first_drv_open>:                 
bf000000 t first_drv_open     [first_drv]
00000018        
pc = bf000018

这里的00000018 就是.s出错的地址,后面有汇编代码,可以确定是哪个寄存器,根据上面寄存器的值,就可以得出哪里出错。

文章来源:海思 https://www.ebaina.com/articles/140000004860

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux Vmlinux反汇编操作和 oops stack 回朔分析 的相关文章

随机推荐

  • 如何使用overleaf&LaTeX

    Introduction What is LaTeX LaTeX是一种基于 的排版系统 由美国计算机学家莱斯利 兰伯特 Leslie Lamport 在20世纪80年代初期开发 利用这种格式 即使使用者没有排版和程序设计的知识也可以充分发挥
  • Python: list列表的11个内置方法

    前言 在实际开发中 经常需要将一组 不只一个 数据存储起来 以便后边的代码使用 在VBA中有使用数组 可以把多个数据存储 到一起 通过数组下标可以访问数组中的每个元素 Python 中没有数组 但是加入了更加强大的列表 list 下面就对列
  • 从输入URL到浏览器显示页面到底经历了什么?

    文章目录 从输入URL到浏览器显示页面到底经历了什么 DNS解析 1 DNS解析过程 2 DNS优化 建立TCP连接 1 什么是TCP 2 TCP的连接建立 三次握手 3 为什么是三次握手 发送HTTP请求 1 请求行 2 HTTP缓存优化
  • Yii Framework 开发教程(29) Zii组件-Menu 示例

    介绍完Yii数据库接口外 从本篇开始介绍Zii组件 包括列表视图ListView 表格视图GridView 此外还包括一些基于JQuery的UI组件 如AutoComplete DataPicker Button Drag 和 Drop等
  • 用Java生成N个不重复的随机数,3种实例

    1 Random类和Set集合来完成 Java实现生成n个不重复的随机数可以使用Java中的Random类和Set集合来完成 具体代码如下 import java util HashSet import java util Random i
  • el-table 中嵌入el-input 输入框无法输入问题(已解决)

    在使用elment ui中的el table 中嵌入el input 会出现 input 无法输入的情况 最后找到了问题的根源 是有时候获取到了数据 但是视图并没有更新 修改前代码
  • STM32f103系列 USART2 USART3 串口2和串口3通信

    最近在做一个工程要用到多个串口同时通讯的 就参考了正点原子的串口通讯例程 发现例程是USART1 串口1的 后面我想改成USART2 串口2的 上网找了资料 要不是不靠谱 要不就是要积分下载 所以后面自己写了一个可用程序来和大家分享 废话不
  • 期货反向跟单犯法吗?

    本篇文章给大家为分析一下关于 期货反向跟单犯法吗 这个疑问 对于想从事或正在运作跟单交易的朋友们来说有必要看一下 做反单跟单不同于做一个黑平台 黑平台的利润是来源于客户的亏损 而做反单的利润来源是市场 和杀羊具有本质区别 不存在什么违法行为
  • 【Educoder作业】C++ 面向对象 - 类的继承与派生

    Educoder作业 C 面向对象 类的继承与派生 关于继承 更多的是关注它的意义 在代码量很少的时候用处不大 大不了再写一个 但是当完成一些工作量比较大的工程时 继承就会避免我们重复的写很多东西 T1 公有继承 学生信息类 关注一下如何继
  • SpringBoot中使用Log4j2

    一 简介 slf4j是日志接口 logback和log4j2是其实现 log4j2的并发效率优于logback 二 SpringBoot中使用log4j2 由于SpringBoot中默认使用logback作为其日志框架 因此如果需要替换为l
  • VS报错runtime check failure #2的解决办法

    第一类 如果后续报错变量为指针类型 检查数组下标访问是否正确 有可能是越界访问 第二类 如果不是指针变量 可以将该局部变量改为全局变量
  • static_cast、dynamic_cast、const_cast和reinterpret_cast总结

    前言 这篇文章总结的是C 中的类型转换 这些小的知识点 有的时候 自己不是很注意 但是在实际开发中确实经常使用的 俗话说的好 不懂自己写的代码的程序员 不是好的程序员 如果一个程序员对于自己写的代码都不懂 只是知道一昧的的去使用 终有一天
  • 【读点论文】Image Style Transfer Using Convolutional Neural Networks(将卷积特征图提取语义信息,融合内容和风格的做法)

    Image Style Transfer Using Convolutional Neural Networks 以不同风格呈现图像的语义内容是一项困难的图像处理任务 可以说 以前的方法的一个主要限制因素是缺乏明确表示语义信息的图像表示 从
  • java 文字转语音

    使用 jacob project 插件 注意 jacob不支持linux jacob是 JAVA COM Bridge 的缩写 是一个中间件 能够提供自动化访问MS系统下COM组件和 Win32 libraries 的功能 并且jacob只
  • Jsp+Servlet+JavaBean到EJB,再到Spring,最后到SpringBoot

    一 知史可以明鉴 我们学习技术的时代赶上了最好的时代 跳过了很多前人经常踩的坑 前人在踩坑的过程中总结了很多经验和教训 而新时代的我们只是继承了前人的经验和教训 而忽略了这些采坑的过程 以至于我们面对很多新技术都不知道他是什么 他为什么存在
  • Unity项目较大刷新及编译卡顿解决方法

    开发中当Unity项目比较大的时候 每次Unity窗口获取焦点时刷新需要3 5秒 非常麻烦 常见有几种方法来缓解这个问题 关闭unity自动刷新Edit gt Preferences gt General gt Auto Refresh 改
  • Spring Boot中整合WebSocket

    要在Spring Boot中整合WebSocket 需要进行以下步骤 1 创建一个Spring Boot项目 使用Spring Initializr创建一个新的Spring Boot项目 选择适当的Spring Boot版本和依赖项 添加W
  • 客户机操作系统已禁用 CPU。请关闭或重置虚拟机。

    VMware 安装CentOS7关机时提示 客户机操作系统已禁用 CPU 请关闭或重置虚拟机 之前一直使用的是CentOS6 5 关机的时候使用的halt命令 一直都可以正常关机 今天安装了CentOS7 使用halt命令关机的时候弹出了下
  • 通过Arduino ESP8266向闪存文件系统上传文件

    通过Arduino ESP8266向闪存文件系统上传文件 下载 Arduino ESP8266闪存文件插件程序 您有两种方法可以下载该插件程序 第一种方法是通过点击此链接进入 Arduino ESP8266官方GitHub页面下载 详情请见
  • Linux Vmlinux反汇编操作和 oops stack 回朔分析

    1 Linux Vmlinux反汇编操作和代码分析 1 1 对vmlinx反汇编 arm linux gnueabi objdump d vmlinux gt debug s 1 2 debug s代码段分析 vmlinux file fo