说明

分享一种crash问题定位的一种解决方法,仅供参考。

ARM32平台上通过错误使用内存,触发系统异常,系统崩溃。系统异常被挂起后,能在串口中看到异常调用栈打印信息和关键寄存器信息。

如下所示,excType表示异常类型,值为4表示数据终止异常,其它数值可以查看芯片手册。

通过这些信息可以基本定位到异常所在函数和其调用栈的关系,为分析系统死机崩溃提供分析,便于查找问题所在。

crash日志

[11:31:32.475]收←◆--- device idle,timeout=10000,lastT=77601,curT=87612
orbSendcmd: | F5 AE 02 FE 04 00 33 00 00 00 26 FD |
data_abort fault fsr:0x29, far:0x00000001
Abort caused by a read instruction. Domain fault, section
excType = 0x4
taskName = DeviceStaThd
taskID = 29
task stackSize = 24576
system mem addr = 0x40aaecc0
excBuffAddr pc = 0x4004cf34
excBuffAddr lr = 0x400522dc
excBuffAddr sp = 0x400f8340
excBuffAddr fp = 0x41300354
R0         = 0x1
R1         = 0x0
R2         = 0x7fffffff
R3         = 0xffffffff
R4         = 0x7fffffff
R5         = 0x1
R6         = 0x0
R7         = 0x0
R8         = 0x0
R9         = 0x1
R10        = 0x0
R11        = 0x41300354
R12        = 0xffffffff
CPSR       = 0x20000013
*******backtrace begin*******
traceback 0 -- lr = 0x 400537ec    fp = 0x4130065c
traceback 1 -- lr = 0x40054a74    fp = 0x4130075c
traceback 2 -- lr = 0x40055ab8    fp = 0x41300824
traceback 3 -- lr = 0x40471a8c    fp = 0x41300c9c
traceback 4 -- lr = 0x40145f54    fp = 0x41300d24
traceback 5 -- lr = 0x40146384    fp = 0x41300db4
traceback 6 -- lr = 0x40146930    fp = 0x41300dc4
traceback 7 -- lr = 0x40046c58    fp = 0x41300dd4
traceback 8 -- lr = 0x4005044c    fp = 0xb0b0b0b

利用反汇编文件.asm

打开编译后生成的 asm 反汇编文件

搜索PC指针 0x4004cf34 在asm文件中的位置(去掉0x)。

PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值 4004cf34,找到当前CPU正在执行的指令行,得到如下所示结果。

4004cf20 <memchr>:
4004cf20:   e3100003    tst r0, #3
4004cf24:   e6ef1071    uxtb    r1, r1
4004cf28:   0a000010    beq 4004cf70 <memchr+0x50>
4004cf2c:   e3520000    cmp r2, #0
4004cf30:   0a000035    beq 4004d00c <memchr+0xec>4004cf34:  e5d03000    ldrb    r3, [r0]4004cf38:   e1530001    cmp r3, r1
4004cf3c:   0a000042    beq 4004d04c <memchr+0x12c>
4004cf40:   e2803001    add r3, r0, #1
4004cf44:   ea000004    b   4004cf5c <memchr+0x3c>
4004cf48:   e3520000    cmp r2, #0
4004cf4c:   0a00002e    beq 4004d00c <memchr+0xec>

ldrb指令作用:LDRB指令用于从内存中将一个8位的字节数据读取到指令中的目标寄存器中。并将寄存器的高24位清零。

LDRB R0, [R2,#3]    ;将内存单元(R2+3)中字节数据读取到R0中,R0中高24位设置成0

LDRB R0,[R1]    ;将内存单元(R1)中的字节数据读取到R0中,R0中高24位设置成0

结合指令分析:寄存器r0读到r3,r0为0x1,r3为0xffffffff,r3超出内存范围

cpu执行该命令发生了数据终止异常。可以确认,memchr 被调用拷贝时可能因为长度问题导致异常

根据 LR链接寄存器值 查找调用栈

从异常信息的backtrace begin开始,打印的是调用栈信息。在asm文件中查找backtrace 0 400537ec 对应的LR,如下所示。

400537e4:    e1a00009    mov r0, r9
400537e8:   ebfffab4    bl  400522c0 <strnlen>400537ec:   e7d93000    ldrb    r3, [r9, r0]400537f0:   e0896000    add r6, r9, r0
400537f4:   e3530000    cmp r3, #0
400537f8:   0affff12    beq 40053448 <printf_core+0xb48>
400537fc:   eafffe12    b   4005304c <printf_core+0x74c>
40053800:   e3170b02    tst r7, #2048   ; 0x800
40053804:   1a000255    bne 40054160 <printf_core+0x1860>
40053808:   e51f3c90    ldr r3, [pc, #-3216]    ; 40052b80 <printf_core+0x280>
4005380c:   e2072001    and r2, r7, #1
40053810:   e51b12e0    ldr r1, [fp, #-736] ; 0xfffffd20
40053814:   e3520000    cmp r2, #0
40053818:   e2832005    add r2, r3, #5
4005381c:   13a01001    movne   r1, #1
40053820:   e50b12e0    str r1, [fp, #-736] ; 0xfffffd20
40053824:   11a03002    movne   r3, r2
40053828:   e50b32e4    str r3, [fp, #-740] ; 0xfffffd1c

可见,是 strnlen 调用了 memchr。

我们从strnlen中的实现也可以确定此论证

使用backtrace begin和源码排查

但是此信息还不足以确定问题,我们可以继续从backtrace begin提供的内存地址开始找

从backtrace1中我们确定为printf_core接口导致

traceback 1 -- lr = 40054a74    fp = 0x4130075c
40054a70:   ebfff7a2    bl  40052900 <printf_core>
40054a74:   e1a05000    mov r5, r0
40054a78:   e3580000    cmp r8, #0
40054a7c:   0a00000d    beq 40054ab8 <vfprintf+0x110>
40054a80:   e5943024    ldr r3, [r4, #36]   ; 0x24

通过与代码结合,底层接口实现查找,确实如图所示

继续根据traceback 2 -- lr = 40055ab8    fp = 0x41300824找到printf_core为vprintf调用

traceback 2 -- lr = 40055ab8    fp = 0x41300824
40055ab4:   ebfffbbb    bl  400549a8 <vfprintf>
40055ab8:   e1a05000    mov r5, r0
40055abc:   e30a337c    movw    r3, #41852  ; 0xa37c
40055ac0:   e1a00005    mov r0, r5
40055ac4:   e3443001    movt    r3, #16385  ; 0x4001
40055ac8:   e5932000    ldr r2, [r3]
40055acc:   e51b3020    ldr r3, [fp, #-32]  ; 0xffffffe0
40055ad0:   e0332002    eors    r2, r3, r2
40055ad4:   1a00001a    bne 40055b44 <vsnprintf+0x118>

根据底层代码实现也可验证无问题

继续往上查找,基本可以确定是打印接口导致

traceback 3 -- lr = 40471a8c    fp = 0x41300c9c
40471a88:   ebef8fe7    bl  40055a2c <vsnprintf>
40471a8c:   e1a00005    mov r0, r5
40471a90:   ebef81b7    bl  40052174 <strlen>
40471a94:   e2402001    sub r2, r0, #1
40471a98:   e7d53002    ldrb    r3, [r5, r2]
40471a9c:   e353000a    cmp r3, #10
40471aa0:   0a000008    beq 40471ac8 <orbbec_log_print+0xe8>

继续往上查找我们是通过哪个方法的打印接口导致的crash

traceback 4 -- lr = 40145f54    fp = 0x41300d24
40145f50:   eb0caea2    bl  404719e0 <orbbec_log_print>
40145f54:   e3e00000    mvn r0, #0
40145f58:   eaffffe3    b   40145eec <_ZN17CDeviceStaManager25DeviceHealthStatusMonitorEPc+0x2d4>traceback 5 -- lr = 40146384    fp = 0x41300db4
40146380:   ebfffe24    bl  40145c18 <_ZN17CDeviceStaManager25DeviceHealthStatusMonitorEPc>
40146384:   e51b3048    ldr r3, [fp, #-72]  ; 0xffffffb8
40146388:   e1530006    cmp r3, r6
4014638c:   1affffa8    bne 40146234 <_ZN17CDeviceStaManager13DeviceStaProcEv+0x1a0>traceback 6 -- lr = 40146930    fp = 0x41300dc4
40146904 <_ZN17CDeviceStaManager12DeviceStaThdEPv>:
40146904:   e30e1464    movw    r1, #58468  ; 0xe464
40146908:   e92d4830    push    {r4, r5, fp, lr}
4014690c:   e1a04000    mov r4, r0
40146910:   e3441076    movt    r1, #16502  ; 0x4076
40146914:   e28db00c    add fp, sp, #12
40146918:   e3a0000f    mov r0, #15
4014691c:   ebfdc7d0    bl  400b8864 <prctl>
40146920:   e3540000    cmp r4, #0
40146924:   0a000001    beq 40146930 <_ZN17CDeviceStaManager12DeviceStaThdEPv+0x2c>
40146928:   e1a00004    mov r0, r4
4014692c:   ebfffdd8    bl  40146094 <_ZN17CDeviceStaManager13DeviceStaProcEv>
40146930:   e3a00000    mov r0, #0
40146934:   e8bd8830    pop {r4, r5, fp, pc}

再根据死机前对信息最后打印可以确定问题所在了,发送完此命令后的一条打印导致的问题

[11:31:31.083]收←◆31 08:01:26.221 [wifi] wifi status check = not connect, retry = 86[11:31:32.082]收←◆31 08:01:27.221 [wifi] wifi status check = not connect, retry = 87[11:31:32.475]收←◆--- device idle,timeout=10000,lastT=77601,curT=87612
orbSendcmd: | F5 AE 02 FE 04 00 33 00 00 00 26 FD |
data_abort fault fsr:0x29, far:0x00000001
Abort caused by a read instruction. Domain fault, section

所以到这里,问题可以确定为

DeviceStaThd()->DeviceStaProc()->DeviceHealthStatusMonitor()
->printf("orbSendcmd")->后一条printf导致的crash

总结

1. LR

LR用途有二,一是保存子程序返回地址,当调用BL、BX、BLX等跳转指令时会自动保存返回地址到LR;二是保存异常发生的异常返回地址。

2. PC

PC(Program Counter)为程序计数器,用于保存程序的执行地址,在ARM的三级流水线架构中,程序流水线包括取址、译码和执行三个阶段,PC指向的是当前取址的程序地址,所以32位ARM中,译码地址(正在解析还未执行的程序)为PC-4,执行地址(当前正在执行的程序地址)为PC-8。
当突然发生中断的时候,保存的是PC的地址。如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq #4。

3. SP

每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。

ARM32平台系统crash(系统崩溃) 问题定位的一种解决方法相关推荐

  1. 64位win10系统无法安装.Net framework3.5的两种解决方法【转】

    64位win10系统无法安装.Net framework3.5的两种解决方法[转] 参考文章: (1)参考文章1:64位win10系统无法安装.Net framework3.5的两种解决方法[转] ( ...

  2. 计算机连接未识别的网络,Win7未识别的网络 Win7系统电脑提示未识别的网络15种解决方法...

    很多用户都是使用ADSL进行连接宽带上网,想必在连接的时候可能会碰到win7系统桌面的网络连接图标总是那边一直转连不上,然后就会提示未识别的网络,网络怎么也连接不上,要怎么办呢,针对这个问题,下面给大 ...

  3. c语言蓝屏代码大全,window_Win10系统出现蓝屏提示错误代码0x00000050两种解决方法,  刚刚升级Win10系统的一段 - phpStudy...

    Win10系统出现蓝屏提示错误代码0x00000050两种解决方法 刚刚升级Win10系统的一段时间,容易出现蓝屏的问题.导致蓝屏故障的原因各不相同,我们需要根据错误代码来执行正确的解决方法.比如,最 ...

  4. w10新建文件夹就卡死_Win10系统新建文件夹假死的3种解决方法

    在使用win10系统的过程中,我们经常会在电脑中新建文件夹来使用,可是有win10系统用户却遇到了新建文件夹假死的情况,想必有很多用户也遇到过一样的情况吧,针对这个问题,小编就给大家带来Win10系统 ...

  5. 64位win10系统无法安装.Net framework3.5的两种解决方法

    近日有网友反映在windows10_64位系统电脑上安装Net framework3.5,操作时总失败,怎么办呢?小编下面就介绍win10 64位系统无法安装Net framework3.5的两种解决 ...

  6. 关闭自动降频 linux,在Deepin系统下CPU不能自主降频的两种解决方法

    如果你在Deepin系统下遇到CPU不能自主降频的问题,可用以下两种方法来解决.因为测试了一下针对笔记本装Deepin系统有时候遇到不能自主降频的问题,导致温度过高,结果用解决方法一处理好了.相关参考 ...

  7. aftershokz蓝牙搜不到_小米MIUI系统无法开启蓝牙耳机aac解码的一种解决方法

    8/1更新:MIUI12现已经开放公测啦!直接去社区申请即可,答题90分,等几个小时很容易就能通过审核.不用费力刷机了,亲测MIUI12开发版可开启蓝牙aac ps.最近看评论区发现可能有个别型号蓝牙 ...

  8. 锚点定位的三种解决方法

    因为在项目中遇到锚点定位的问题,觉得有必要单独成文,来介绍锚点定位的解决办法. 一 学习锚点定位之前的知识储备: 1.1 #号的作用 #代表网页中的一个位置.其右面的字符,就是该位置的标识符.比如,h ...

  9. 服务器安装系统提示无法创建新的系统分区,Win10系统安装时提示无法创建新的系统分区也无法定位现有的分区的三种解决方法...

    部分用户在安装Windows10系统时,却遇到"无法创建分区也找不到现有的分区"提示,无法继续安装.这该怎么办呢?对于该问题大家可以参考以下方法来解决. 1.格式化整个硬盘,重新分 ...

最新文章

  1. linux查询数据库sql,SQL Server 跨数据库查询
  2. 机器人或抢走2000万人“饭碗”
  3. MFC中进度条控件的使用方法
  4. 互逆矩阵特征值,奇异值的关系
  5. 杀java_java怎么杀掉java进程
  6. css使按钮固定在界面上面
  7. Docker 简介 安装
  8. vivado中的OOC技术
  9. show,hide与fadeIn、fadeOu的区别
  10. 一、用户画像是如何生成的
  11. samba服务testparm时提示rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384)处理办法
  12. Halcon颜色分类-MLP
  13. android在wifi和4G网络都可以使用的情况下,设置每次请求使用的网络类型
  14. ESXi 5.5 安装Emulex光纤卡驱动
  15. pythontrun什么意思_python新手笔记一
  16. 1.两数之和(python)
  17. 你怎么看欧阳娜娜空降阿里p8?
  18. php fpm 指定用户,php-fpm-请不要用root作为php工作用户
  19. 如何高效管理电脑里的文件
  20. 【MPPT】基于MPPT的风力发电系统simulink仿真

热门文章

  1. matlab的newff函数是用来,[转载]matlab神经网络newff函数的使用
  2. 算法基础知识——动态规划
  3. C#在unity上实现双指缩放
  4. PAT 基础编程题 7-8 超速判断 (10 分)
  5. pyqtgraph的使用
  6. 点击按钮,回到页面顶部的5种写法
  7. ant design pro v5 总结
  8. Your Birthday
  9. Android 11.0 framework添加自定义开机广播
  10. 双向循环链表、dancing links