使用 QEMU 模拟 cortex-a8 的断点在 gdb 中不起作用

Breakpoint not working in gdb with QEMU simulating cortex-a8

我正在ARM7TDMI中测试一些简单的代码运行ning,由于我在QEMU上没有找到ARM7TDMI模拟器,所以我改用Cortex-a8(我不确定这是否会导致错误,总新手)。
我就是这样 运行 QEMU:
qemu-system-arm -machine realview-pb-a8 -cpu cortex-a8 -nographic -monitor null -serial null -semihosting -kernel main.elf -gdb tcp::51234 -S

我要测试的代码很简单,函数LoadContext()SaveContext()是为IARIDE用arm汇编编写的,而IARIDE是以ARM7TDMI为核心。我把这个汇编文件用IAR编译成目标文件,link下面的代码用arm-none-eabi-gcc,会不会出现不可预知的错误? (只想使用 gcc 和 QEMU 而不是 IAR...)

int main(void)
{

    Running = &taskA;
    Running->PC = task1;
    Running->SP = &(Running->StackSeg[STACK_SIZE-1]);

    LoadContext();
}

void task1(void)
{
    register int reg_var = 1;
    volatile int vol_var = 1;

    SaveContext();
    reg_var++;
    vol_var++;

    SaveContext();
    reg_var++;
    vol_var++;

    LoadContext();
}

所以,当我在 gdb 中设置断点时,它不起作用,我认为它只会进入无限循环。我查看了初始化过程,是:

(gdb) 
0x000082f6 in __libc_init_array ()
(gdb) 
0x000080e2 in _start ()
(gdb) 
0x000080e4 in _start ()
(gdb) 
0x000080e6 in _start ()
(gdb) 
main () at src/context-demo.c:12
12  int main(void) {
(gdb) 
0x000081ea  12  int main(void) {
(gdb) 
0x00000008 in ?? ()
(gdb) 
0x0000000c in ?? ()
(gdb) 
0x00000010 in ?? ()
(gdb) 
0x00000014 in ?? ()
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000004 in ?? ()
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00000004 in ?? ()
(gdb) 

有人知道这里发生了什么吗?感谢任何帮助,谢谢!

如果你告诉 gdb 告诉你它正在执行的汇编指令,你会发现这更容易调试("display /3i $pc" 每次 gdb 停止时都会打印接下来的 3 条指令),并执行单步操作个别指令("stepi")。

某事导致您意外地以低地址 0x8 结束,您需要查明那是什么。要么你真的跳到 0x8,要么你采取了例外。查看每机器指令级别的执行会告诉您它是什么。

这里有一些似是而非的可能性:

  • 可执行文件假设它有 RAM 而 realview-pb-a8 没有 RAM——这通常表现为 "writing to the stack (or global variables) silently does nothing and reading from the stack/globals returns 0",所以如果你在全局中有一个函数指针或者你试图推送一个 return 地址到堆栈然后弹出它你会在 0
  • 可执行文件被构建为假设它是 运行 在提供 SVC API 的 OS 下——在这种情况下,代码将执行 SVC 指令并且您的代码将崩溃,因为有在 SVC 异常向量
  • 没有什么可以处理的
  • 为错误的 CPU 类型构建的可执行文件并执行 UNDEF 的指令(这应该导致执行地址 0x4,即 undef 向量,但我感觉它的 gdbstub 中有一个 qemu 错误可能意味着执行 UNDEF insn 的步骤将不会停止,直到在 UNDEF 向量处执行第一个 insn 之后)
  • 构建的可执行文件假定 FPU 始终处于启用状态。当 QEMU 像这样执行 "bare metal" 二进制文件时,CPU 在硬件启动的状态下启动,其中 FPU 被禁用。因此,除非可执行文件的启动代码已明确打开 FPU,否则任何使用 FPU 的指令都将 UNDEF。

我已经按照您的案例的大致概率顺序列出了这些,但无论如何,机器指令的单步执行应该可以确定发生了什么。