设为首页 加入收藏

TOP

arm平台的调用栈回溯(backtrace)(二)
2019-09-01 23:09:57 】 浏览:64
Tags:arm 平台 调用 回溯 backtrace
c-7.3默认选项编译结果如下,fp已经不在了,虽然这里仍然可能通过r7得知上个栈帧的位置,但是已经没法使用fp获取栈帧了。此时是不保证栈帧保存在栈中的。所以依赖栈帧内容进行恢复已经非常不可靠。那么既然无法依赖fp,那该怎么进行栈帧回溯呢,gnu说使用unwind方法回溯,这节暂时不会介绍unwind方法。

000103c8 <func1>:
    103c8:   b580        push    {r7, lr}
    103ca:   b082        sub sp, #8
    103cc:   af00        add r7, sp, #0
    103ce:   2300        movs    r3, #0
    103d0:   607b        str r3, [r7, #4]
    103d2:   f240 4048   movw    r0, #1096   ; 0x448
    103d6:   f2c0 0001   movt    r0, #1
    103da:   f7ff ef7e   blx 102d8 <puts@plt>
    103de:   687b        ldr r3, [r7, #4]
    103e0:   4798        blx r3
    103e2:   2300        movs    r3, #0
    103e4:   4618        mov r0, r3
    103e6:   3708        adds    r7, #8
    103e8:   46bd        mov sp, r7
    103ea:   bd80        pop {r7, pc}

 000103ec <main>:
    103ec:   b580        push    {r7, lr}
    103ee:   af00        add r7, sp, #0
    103f0:   f7ff ffea   bl  103c8 <func1>
    103f4:   2300        movs    r3, #0
    103f6:   4618        mov r0, r3
    103f8:   bd80        pop {r7, pc}

使用栈帧进行回溯

这一节使用gcc4.7版本,默认编译选项编译出来的程序,演示调用栈回溯。该编译选项下,压栈的寄存器为{fp, lr}。

下边的内容是一段core dump中的寄存器和调用栈,本节将对这段内容进行回溯。

Reg:         r9, Val = 0xf7578000;  Reg:        r10, Val = 0x00000001;  
Reg:         fp, Val = 0x827d3104;  Reg:         ip, Val = 0xf7578ae0;  
Reg:         sp, Val = 0x827d30e0;  Reg:         lr, Val = 0xf7549990;  
Reg:         pc, Val = 0xf7548c20;  Reg:       cpsr, Val = 0x60000210;

0x827d30e0: 0x00000031  0x827d31a0  0x00000001  0xd5dff060  
0x827d30f0: 0xd5e0e6b1  0xd5dec134  0xf7578000  0xf7577c40  
0x827d3100: 0x827d313c  0xf7549990      
0x827d3140: 0x00000000  0xd5dec104  0xf7568514  0x00000002  
0x827d3150: 0xd5dec104  0xf7577c40  0xf7577c38  0xd5de9224  
0x827d3160: 0x827d31a0  0xf757a084  0xf7577c40  0xd5df6dd4  
0x827d3170: 0x827d3194  0x00000001  0xd5e0e678  0xd5dec104  
0x827d3180: 0xd5de9224  0xf7568548  0x00000000  0xf7568550  
  1. 当前sp地址为0x827d30e0,fp地址为0x827d3104,从而得知当前函数frame0的栈帧。fp指向的地址0x827d3104为frame1的lr,0x827d3100为上一个栈帧的fp。
0x827d30e0: 0x00000031  0x827d31a0  0x00000001  0xd5dff060  
0x827d30f0: 0xd5e0e6b1  0xd5dec134  0xf7578000  0xf7577c40  
0x827d3100: 0x827d313c(fp)  0xf7549990(lr)
  1. 从frame0的fp地址0x827d313c可知,frame1的调用栈起始地址,去掉frame0的内容,得到frame1的栈帧。
                                                                        0x827d312c  0xf7530c14  
0x827d3110: 0xd5dff060  0x0000002c  0xd5e0e6b1  0xd5e0e6b1  
0x827d3120: 0x00000001  0xd5e0e6b1  0xd5dff060  0xd5dec134  
0x827d3130: 0xf7578000  0xf7577c40  0x827d3194(fp)  0xf754ad0c(lr)
  1. 依次类推,依次得到frame2、frame3...的栈帧。

当汇编代码的函数调用使用push {fp, ip, lr, pc}时,则上一个栈帧的fp2在当前栈帧的(fp - #4)位置。栈帧的回溯要结合程序的汇编代码具体分析,有可能程序并不使用fp指针,也有可能栈中根本没有保存fp。

unwind方法回溯

TODO

附录1-函数调用标准缩略语

  • PCS Procedure Call Standard.
  • AAPCS Procedure Call Standard for the ARM Architecture (this standard).
  • APCS ARM Procedure Call Standard (obsolete).
  • TPCS Thumb Procedure Call Standard (obsolete).
  • ATPCS ARM-Thumb Procedure Call Standard (precursor to this standar

参考资料

  1. ARM 体系结构概述
  2. Procedure Call Standard for the ARM® Architecture
  3. GCC 5 Release Series
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇详解SPI中的极性CPOL和相位CPHA 下一篇Linux的命名空间详解--Linux进程..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目