在QEMU中调试早期的内核启动代码

时间:2019-04-17 08:09:49

标签: c assembly arm gdb qemu

我有一些代码(包含汇编代码和C语言),已编译为ELF二进制文件,QEMU中的某些固件/引导程序代码在特定的物理地址处加载。 ELF使用虚拟地址链接;但是,该代码应在MMU关闭的情况下运行,这意味着它必须与位置无关。

问题在于PC设置为入口点的物理地址,这很有意义,但是由于所有符号都是使用虚拟地址引用的,因此GDB不知道入口点在哪里。

我仍然可以在MMU打开时调用的函数上设置断点(因此PC将在该点处理虚拟地址),但这不足以调试早期代码,包括单步执行。

我已经能够通过使用物理地址将其链接来调试此代码,但是很明显,一旦我打开MMU,这就会造成问题。

有人知道我在这里想念什么吗?

1 个答案:

答案 0 :(得分:1)

我认为您的问题不是QEMU(甚至ARM)所特有的。我相信至少有三种方法可以解决这个问题,

  1. 只需使用汇编程序
  2. 使用symbol-file
  3. 叠加层

汇编器

我遇到了这个问题,但是只是切换到检查汇编器。这非常容易,特别是如果您objdump -S将MMU /普通地址版本匹配到汇编程序。您可以将objdump输出通过管道传输到文件,并根据需要删除未重定位的代码。但是,大多数编辑器都可以处理大文件。

查看汇编程序可能会非常有帮助,因为某些重定位常量或非PIC类型引用经常不正确。您需要代码/数据都是正确的,并且您的PIC代码可能会调用某些gcc库例程,该例程链接到您没有考虑的地方。因此,尽管这是原始的,但确实具有一些优点。

符号文件

另一种方法是将symbol-file中的内容使用起来。在引导过程中,将物理链接与symbol-file一起使用,然后在MMU切换后,将MMU /普通链接的symbol-file用于。显然加载MMU版本。

重叠

我认为您可以使用overlays来解决这个问题,尽管您实际上是在做相反的事情。 VMA是MMU地址,而LMA是物理启动地址。最初将其标记为已映射,然后在打开MMU时可以用_ovly_debug_event()更新。

叠加层带有代码,但这是最方便的。如果您在软件开发系统中已经有一个“调试”构建目标并将其条件化,我将尝试这样做。但是,如果您在ld中使用实际的叠加层,它实际上可以解决您的某些问题,并且您可能会发现它最可靠。覆盖资源的影响很小,但确实存在。


参考

参考是关于为什么要调试它的编码问题。