ARM_UNWIND_BACKTRACE

本文介绍了ARM处理器中使用.ARM.exidx和.ARM.extab进行异常回溯的原理和过程,包括prel31解码、字节码反汇编等。通过分析函数符号表和链接脚本,展示了如何在代码中启用和利用unwind回溯功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码仓: https://codechina.youkuaiyun.com/fu851523125/arm_unwind_backtrace.git

 

参考文章:arm上backtrace的分析与实现原理_流风回雪的博客-优快云博客

2.2 unwind

对于APCS来说,优点是分析起来比较简单,跟踪起来也可以很容易。缺点就是指令过多,栈消耗大,占用的寄存器也过多,比如每次调用 都必须将r11,r12,lr,pc入栈。为了解决这个问题,提出了第二种方案:

使用unwind就能避免这些问题,生产指令的效率要有用的多。unwind是最新的编译器(>gcc-4.5)为arm支持的新特性。它的原理是记录每个函数的入栈指令(一般比APCS的入栈要少的多)到特殊的段.ARM.unwind_idx .ARM.unwind_tab。

所以如果我们要使用unwind,就必须在链接文件中定义这个段

.ARM.exidx : {

__exidx_start = .;

*(.ARM.exidx* .gnu.linkonce.armexidx.*)

__exidx_end = .;

}

我们也可以通过arm-none-eabi-readelf -u xxxxx.elf查看其内容。

 

以上面两个为例,set_date的函数的地址是0xc007c4a0,而set_time的函数的地址是0xc00a0fb0。

 

而r11也就是fp地址在unwind_tab段中,也就是位于0xc00a0fa4地址处。

回溯时根据pc值到段中得到对应的编码,解析这些编码计算出lr在栈中的位置,进而计算得到调用者的执行地址。

一般来说,我们使用unwind优势比使用apcs更好,因为采用apcs时,会产生更多的代码指令,对性能有影响,但是使用unwind方式只会产生一个额外的段空间,并不会影响性能,所以大多数情况下,使用unwind更加有利。

unwind回溯的过程可以总结为三部分:

1.根据pc找到函数unwind的段内存地址

2.根据unwind段中信息找到指令相关的编码数据

3.根据入栈地址,分析函数上一级的栈底保存的sp和lr。

03

函数符号表

栈回溯的过程中,往往需要符号表来进行操作,此时需要开启-mpoke-function-name这个编译选项。

使用这个选项编译出的二进制程序中可以包含 C 语言函数名称的信息,以方便函数调用链回溯时记录信息的可读性。

比如在Linux中,系统死机后,可以打印出栈的地址和函数的名称,根据这个进行回溯操作就可以进行使用了。

基本原理就是加上-mpoke-function-name后,在每段代码段后面,都会附加一个函数的符号,我们需要使用的时候,就根据函数的pc指针,然后找到相关的偏移量,之后将这个代码段的符号获取到了。

 

 

参考文章: [原创] ARM栈回溯——从理论到实践,开发ida-arm-unwind-plugin-Android安全-看雪论坛-安全社区|安全招聘|bbs.pediy.com

.ARM.exidx 结构

这个 section 连续存放Entry,视为一个Entry数组。先要处理大小端问题,处理好后,每个 Entry 由两个 uint16 组成,相当于如下 struct:

1

2

3

4

struct EHEntry {

  uint32_t Offset;

  uint32_t World1;

};

EHEntry.Offset 意义是函数起始偏移。最高 bit 一定是 0,结合当前偏移(当前 pc )进行使用 prel31 解码,得到 uint64_t。

 

格式为:

1

2

31----24 23----16 15-----8 7------0 |

0XXXXXXX | XXXXXXXX | XXXXXXXX | XXXXXXXX |

EHEntry.Word1 有三种情况:

  • EHEntry.Word1 == 1 ,表示 CannotUnwind

    1

    00000000 00000000 00000000 00000001 |

  • 最高 bit 为 1,则[31:24]必须为 0b10000000(其实是 personality 为 0,属于 inline compact model),余下 X、Y、Z, 3 个 byte 表示字节码。

    1

    2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值