assembly LABEL PUSH BL指令序列后调试崩溃

btqmn9zl  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(160)

我目前正在尝试调试ARM汇编中的一个简单指令序列。然而,尝试单步调试(使用arm-none-eabi-gdb)会导致调试器总是在一个特定的指令处冻结,并迫使我终止调试会话。调试器不允许我挂起会话来检查是否输入了错误处理程序,因此只能终止会话。
一些环境信息

  • IDE:Eclipse
  • arm-none-eabi-gcc编译器
  • 编译器标志:-mcpu=cortex-m4 -mthumb -00-g3 -ffunction-sections -c
  • 在带有M4的stm32 f4发现板上运行

问题

从我的main函数调用foo,这是我用汇编语言编写的函数。在将非暂存寄存器和LR推入堆栈并为局部变量等腾出空间之后。我在这个汇编函数内部调用另一个汇编函数bar,并将临时寄存器保存在堆栈上。
我的简化程序集文件如下所示:

.syntax unified
.thumb
.text
.global foo
.global bar

bar:
push {r4,r5,r6,r7,r14} //the debugger "freezes" before executing this instruction
add r4,r5
pop {r4,r5,r6,r7,r15}

foo:
push {r4,r5,r6,r7,r14}
subs r13, r13, #124
.foo_bb1:
push {r0}
push {r1}
push {r2}
push {r3}
bl bar
pop {r4,r5,r6,r7,r15}

我的头文件看起来像这样

#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_

#include "stdint.h"
void foo();
void bar();
#endif

我的main.c文件如下所示

int main()
{
    foo();
    return 0;
}

当我连接调试器并进入foo时,在单步执行bl bar指令后,一切都正常。在此指令之后,调试器正确地跳转到bar,但现在调试器冻结(即在执行bar中的push指令之前),除了终止会话之外,我不能做任何其他事情。这也意味着我不能再查看寄存器的内容或检查内存布局。

我所尝试的

我想到的第一件事是检查堆栈指针是否正确对齐。堆栈指针总是8字节对齐。这是在foo的开始处、在subs r13, r13, #124之后以及在执行跳转指令之前的情况。令我惊讶的是,如果我删除所有push {rX}指令,调试器将毫无问题地继续进行。如果我添加一个push指令,问题就会再次出现。我不能完全摆脱存储r 0-r3,所以仅仅删除推送指令并不是一个可行的选择。我可以将函数调用切换到bar以外的其他函数,但这也不会改变行为。

编辑:在创建这个最小示例时,我发现在foo中的那些push {rX}指令之前有一个标签。去掉标签.foo_bb1:,保留push,同样不死机。不幸的是,我也需要标签,不能完全摆脱它。

我试着看看是否遇到了错误处理程序,但似乎不是这样。我还尝试用cpsid i禁用中断,但它没有改变行为。我在跳转之前查看了堆栈布局,看看是否有任何损坏,但我找不到任何奇怪的数据。我试图通过从r13中减去一个较小的数字来减少本地堆栈区域,以查看堆栈是否已满,但没有任何成功。
st community forum中有一个与单步调试有关的问题。这解决了ARM M7和STMf 7的边界,所以也不适合我的问题。尽管如此,我也检查了那里的变通方法,但它也不起作用。
我不知道这是什么样的错误。这是一个STM问题,这是一个调试器问题,这是一个实现错误?如果有人有类似的问题或知道如何解决这个问题,我将非常感激:)

o4tp2gmn

o4tp2gmn1#

好吧...我想我会因为这个被烤熟的:
正如我的编辑已经说过的,在我删除标签.foo_bb1:之后,调试器继续运行,没有错误。有一个相关的问题here。我不认为这与标签或标签名称有任何关系。
简而言之:在标签名称的开头使用大写的“L”,即.Lfoo_bb1:解决了这个问题。

相关问题