stack 数据如下:
0xbefffca8: 0x0000000f 0x00000019 0x00000005 0x00000014
0xbefffcb8: 0x0000000f 0x00000019 0x00000000 0x00010440
0xbefffcc8: 0x00010430 0xb6ea8e7c 0xb6fcb000 0xbefffe24
0xbefffcd8: 0x00000001 0x00010430 0xb6fec71c 0xb6fff884
0xbefffce8: 0xe9b42e1e 0xe1a15cf6 0x00000000 0x00000000
0xbefffcf8: 0x00010294 0x00000000 0x00000000 0x00000000
0xbefffd08: 0xb6fff000 0x00000000 0x00000000 0x00000000
0xbefffd18: 0x00000000 0x00000000 0x00000000 0x00000000
寄存器信息:
r0 0x19 25
r1 0xf 15
r2 0x14 20
r3 0xf 15
r4 0xbefffce8 3204447464
r5 0x0 0
r6 0x10294 66196
r7 0x0 0
r8 0x0 0
r9 0x0 0
r10 0xb6fff000 3070226432
r11 0x0 0
r12 0xb6fcb000 3070013440
sp 0xbefffca8 0xbefffca8
lr 0x10428 66600
pc 0x103d4 0x103d4 <add+12>
cpsr 0x600d0010 1611464720
当前正在执行的函数的汇编代码:
Dump of assembler code for function add:
0x000103c8 <+0>: sub sp, sp, #8
0x000103cc <+4>: str r0, [sp, #4]
0x000103d0 <+8>: str r1, [sp]
=> 0x000103d4 <+12>: ldr r2, [sp, #4]
0x000103d8 <+16>: ldr r3, [sp]
0x000103dc <+20>: add r3, r2, r3
0x000103e0 <+24>: mov r0, r3
0x000103e4 <+28>: add sp, sp, #8
0x000103e8 <+32>: bx lr
从第一个指令可知,add()调用者函数所在的栈的结束地址为 $sp + 8 = 0xbefffcb0.
add() 函数调用的位置为:
(gdb) x /i $lr-4
0x10424 <foo+56>: bl 0x103c8 <add>
再看 foo()的汇编:
0x000103ec <+0>: push {lr} ; (str lr, [sp, #-4]!)
0x000103f0 <+4>: sub sp, sp, #20
0x000103f4 <+8>: str r0, [sp, #4]
0x000103f8 <+12>: str r1, [sp]
0x000103fc <+16>: ldr r2, [sp, #4]
0x00010400 <+20>: ldr r3, [sp]
0x00010404 <+24>: add r3, r2, r3
0x00010408 <+28>: str r3, [sp, #12]
0x0001040c <+32>: ldr r2, [sp, #4]
0x00010410 <+36>: ldr r3, [sp]
0x00010414 <+40>: rsb r3, r3, r2
0x00010418 <+44>: str r3, [sp, #8]
0x0001041c <+48>: ldr r0, [sp, #12]
0x00010420 <+52>: ldr r1, [sp, #8]
0x00010424 <+56>: bl 0x103c8 <add>
0x00010428 <+60>: add sp, sp, #20
0x0001042c <+64>: pop {pc} ; (ldr pc, [sp], #4)
由此可知, $lr 在栈上保存的位置为:
$sp + 8 + 20 = 0xbefffcc4
根据 user stack 数据可知, 0xbefffcc4上的位置的值为
0x00010440
这个即是调用 foo()后的返回地址。
所以,调用 foo()的位置为 0x00010440 -4 = 0x0001043c
(gdb) x /i 0x1043c
0x1043c <main+12>: bl 0x103ec <foo>
再看 main()的汇编:
0x00010430 <+0>: push {r3, lr}
0x00010434 <+4>: mov r0, #20
0x00010438 <+8>: mov r1, #5
0x0001043c <+12>: bl 0x103ec <foo>
0x00010440 <+16>: mov r3, #0
0x00010444 <+20>: mov r0, r3
0x00010448 <+24>: pop {r3, pc}
由此可知,main()的 lr在栈上的位置为:
$sp + 8 + 20 +8 = 0xbefffccc
这里加上8, 是因为, push {r3, lr}是先 push lr, 后 push r3.
再根据 user stack, 查出,在 0xbefffcc8位置,保存的值为:
0xb6ea8e7c
这个是main()的 lr值。
x /i 0xb6ea8e7c - 4
0xb6ea8e78 <__libc_start_main+272>: blx r3
栈的结构如下图: