我目前正在尝试调试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问题,这是一个调试器问题,这是一个实现错误?如果有人有类似的问题或知道如何解决这个问题,我将非常感激:)
1条答案
按热度按时间o4tp2gmn1#
好吧...我想我会因为这个被烤熟的:
正如我的编辑已经说过的,在我删除标签
.foo_bb1:
之后,调试器继续运行,没有错误。有一个相关的问题here。我不认为这与标签或标签名称有任何关系。简而言之:在标签名称的开头使用大写的“L”,即
.Lfoo_bb1:
解决了这个问题。