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

Mar*_*rio 5 c assembly gdb arm qemu

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

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

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

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

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

art*_*ise 1

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

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

汇编器

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

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

符号文件

另一种方法是使用现有的symbol-file. 在启动期间使用物理链路symbol-file,然后symbol-file在 MMU 切换后使用 MMU/正常链路。显然加载MMU版本。

叠加层

我认为你可以用覆盖来处理这个问题,尽管你实际上是在做相反的事情。VMA是MMU地址,LMA是物理引导地址。最初将其标记为映射,然后您可以_ovly_debug_event()在打开 MMU 时进行更新。

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


参考

参考文献是关于为什么您可能想要调试它的编码问题。