GDB 在链接分支(ARM 汇编)后意外继续执行

问题描述 投票:0回答:1

我有一个简单的 ARM 汇编程序(如下),带有指向函数的链接分支,该函数将寄存器压入堆栈并分支回

lr
中的返回地址。

主要.S:

.global _start

.section .text
_start:
    mov     r0, #2      // garbage instructions to show that single step works properly with mov
    mov     r1, #2
    mov     r2, #2
    bl      subr

    mov     r7, #0x1
    mov     r0, #0
    swi     0

subr:
    mov     r0, #1
    push    {r0}
    bx      lr

当我用GDB调试程序并使用

n
单步执行
bl subr
指令时,它会继续到下一个断点而不是单步执行(下面的GIF 1)。当我进入
subr
然后单步跨过
bx lr
时,它会正常单步执行下一条指令(下面的 GIF 2)。我意识到问题是由于
push {r0}
中的
subr
指令造成的。如果将其删除,链接的分支指令将表现正常。

lr
中的地址是
0x10064
,它匹配分支后的下一条指令的地址(第10行):

(gdb) i r lr
lr             0x10064  65636
(gdb) i line 10
Line 10 of "main.S" starts at address 0x10064 <_start+16> and ends at 0x10068 <_start+20>.

Step Over GDB 的 GIF(未按预期工作):

步入(正确):

我在 ARMv6l 架构上的 Raspbian Jessie 2017(QEMU 仿真,我可以使用的最稳定的操作系统)上使用 GDB 7.7.1。

问题:在一个真实的项目中(我目前正在开发一个项目),如何避免单步执行子例程,同时仍然以某种方式将返回值放在堆栈上(如果我做的事情完全错误,请告诉我)?为什么使用

push
指令会发生这种情况?

assembly arm gdb gnu-arm
1个回答
1
投票

您正在使堆栈不平衡,因此 GDB 似乎假定该函数是递归的或仍然处于活动状态,因此在返回主函数时不会停止(因为堆栈不平衡)。 GDB正在等待堆栈返回正常(对于

_start
pc返回到“下一个”指令位置,两者一起,以便在下一个逻辑行处中断(我认为,至少).

不平衡堆栈不好,不仅会扰乱调试器,还会扰乱其他函数,例如,如果此类函数在调用不平衡堆栈的函数之前和之后使用了堆栈,例如保存它自己的返回地址在堆栈上以供稍后使用。

例如,尝试编写相同的代码,其中

_start
调用
main
,然后
main
调用
subr
。这是行不通的,因为
main
必须在调用
_start
之前推送自己的返回地址(即到
subr
),然后弹出它以便返回到
_start
,但它赢了由于堆栈已因
subr
不平衡而无法正确处理。

© www.soinside.com 2019 - 2024. All rights reserved.