基于fp栈回溯
老生常谈,无需多言。
基于.eh_frame栈回溯
https://developer.aliyun.com/article/815064
栈回溯参考文章
https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
.eh_frame 相关资料
据说记录了寄存器的变化,随便找个elf用readelf -wF 来看下里面是个啥。
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329154332231.png)
重新选择方便调试的样本。断点下在JNI_OnLoad ,先看bt给出的完整调用栈,假设崩溃点出现0xeb9cc
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329202122360.png)
0xeb9cc 各寄存器值
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329160924307.png)
.eh_frame 该位置数据
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329160346767.png)
看下有没有翻车
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329172855332.png)
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329173426614-1024x41.png)
frame #1 对应上了,拿到libart.so 的.eh_frame 数据。offset = 0x0000007fcbc7b4a8 – 0x76ebb87000 = 37 CD98
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329153711793.png)
那这里如何去得到x29 寄存器呢,回想一个函数(BL)调用另一个函数的过程。
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220330010607130.png)
先设置ld寄存器,进入函数内部后,将ld寄存器和x29寄存器依次压栈,将x29 指向栈底,那么x29上的值就是caller的x29.
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329203834549.png)
x29 = 0x0000007fcbc7b5e0 ,CFA = x29 + 16 = 0x0000007fcbc7b5f0 ra = *(CFA – 8) = *(0x0000007fcbc7b5e8) = 0x00000076e1a2b0e4
frame #2对应上了,OK 后续类似就不用做了。
![](http://pareto.fun/wp-content/uploads/2022/03/image-20220329202122360-1.png)
0 条评论