当前位置:首页>Linux>ARM Linux Core Dump高阶调试:gdb分析数据中止异常与FAR/FSR寄存器

ARM Linux Core Dump高阶调试:gdb分析数据中止异常与FAR/FSR寄存器

  • 2026-10-11 07:52:59
ARM Linux Core Dump高阶调试:gdb分析数据中止异常与FAR/FSR寄存器

大家好,我是一个爱分享的牛马程序员,工作中碰到,加上自己理解,很高兴给大家分享。

在ARM Linux系统中,数据中止(Data Abort)异常是常见的内存访问错误。结合info registers与disassemble命令,能快速定位非法内存地址、分析异常类型,尤其适合调试ARM架构特有的FAR(Fault Address Register)与FSR(Fault Status Register)寄存器状态。

一、核心考点拆解ARM数据中止调试需关注:

•FAR寄存器:记录导致异常的内存地址;
•FSR寄存器:包含异常类型(如权限错误、未对齐访问)、操作方向(读/写)等信息;
•异常向量表:数据中止入口位于0x10,需验证处理函数逻辑。

二、关键调试命令与实例

1.查看FAR与FSR寄存器使用info registers查看异常时的寄存器状态:

(gdb) info registers far fsr

far            0x55f8d7c20a00  93958556621312  # 非法内存地址

fsr            0x00000005  5  # 异常类型:权限错误(写操作)

分析:fsr的第0-3位为0b0101,表示写操作访问不可写内存。

2.反汇编异常处理函数使用disassemble查看数据中止处理函数:

(gdb) disassemble 0x55f8d7a32b00  # 数据中止入口

Dump of assembler code from 0x55f8d7a32b00 to 0x55f8d7a32b20:

0x55f8d7a32b00 <__vectors+16>:  push    {r4, r5, r6, lr}

0x55f8d7a32b04 <__vectors+20>:  ldr     r0, [sp, #0x14]

0x55f8d7a32b08 <__vectors+24>:  bl      __dabt_usr

0x55f8d7a32b0c <__vectors+28>:  pop     {r4, r5, r6, pc}

3.栈回溯与异常原因定位使用backtrace命令查看调用栈:

(gdb) bt

#0  0x000055f8d7a32b00 in __vectors ()

#1  0x000055f8d7a32b20 in __dabt_usr () from /lib/arm-linux-gnueabihf/libc.so.6

#2  0x000055f8d7a32b40 in memcpy () from /lib/arm-linux-gnueabihf/libc.so.6

#3  0x000055f8d7a32b60 in copy_data (dst=0x7ffd8a6b3200, src=0x55f8d7a32a00, len=2048) at data.c:30

#4  0x000055f8d7a32b80 in main () at main.c:45

发现异常发生在memcpy,因dst地址不可写导致数据中止。

三、ARM特有调试技巧

4.解析FSR寄存器FSR格式(ARMv7):

Bit 31-26: 保留

Bit 25:    0(数据中止)

Bit 24:    0(外部abort)

Bit 23:    0(同步abort)

Bit 22:    0(非精确abort)

Bit 21:    0(无数据访问)

Bit 20:    0(无指令访问)

Bit 19-16: 异常类型(0b0101表示权限错误)

Bit 15:    0(非对齐访问)

Bit 14:    0(无转换)

Bit 13:    0(无权限)

Bit 12:    0(域错误)

Bit 11:    0(访问类型)

Bit 10-0:  保留

5.验证内存权限使用info proc mappings确认地址权限:

(gdb) info proc mappings

...

0x55f8d7c20000 0x55f8d7c41000 0x21000    0x0      [heap]

...

(gdb) x/1xw 0x55f8d7c20a00  # 堆地址可写

0x55f8d7c20a00: 0x00000000

6.处理未对齐访问检查地址是否4字节对齐:

(gdb) p/x $far & 0x3

$1 = 0x0  # 对齐正确,排除未对齐问题

四、实战案例

假设ARM程序因写入只读内存崩溃,代码如下:

int main() {

   volatile unsigned int *reg = (volatile unsigned int *)0x10000000;

   *reg = 0x1234;  // 写入只读寄存器,触发数据中止

   return 0;

}

7.寄存器与异常分析

(gdb) info registers far fsr

far            0x10000000  16777216

fsr            0x00000005  5  # 写权限错误

8.内存映射与权限验证

(gdb) info proc mappings

...

0x10000000 0x10001000 0x1000    0x0      /dev/mem

...

(gdb) x/1xw 0x10000000

0x10000000: Cannot access memory at address 0x10000000

9.反汇编与指令验证

(gdb) disassemble main

Dump of assembler code for function main:

0x55f8d7a32b80 <main+0>:    ldr     r3, [pc, #0x4]

0x55f8d7a32b84 <main+4>:    movs    r0, #0x1234

0x55f8d7a32b88 <main+8>:    str     r0, [r3]

0x55f8d7a32b8c <main+12>:   movs    r0, #0x0

0x55f8d7a32b90 <main+16>:   bx      lr

五、总结ARM数据中止异常调试需结合寄存器与内存分析:

•info registers快速定位FAR与FSR寄存器值;
•disassemble验证异常处理函数逻辑;
•内存映射与权限分析确认访问合法性。

实际调试中,可配合x命令查看内存数据,或使用set修改寄存器值模拟异常场景,提升调试效率。

如果文章对你有提升,帮忙点赞,分享,关注。十分感谢

最新文章

随机文章