首页 > 解决方案 > 在 QEMU 中调试早期内核启动代码

问题描述

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

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

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

我已经能够通过使用物理地址链接它来调试此代码,但显然这将在我打开 MMU 时产生问题。

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

标签: cassemblyarmgdbqemu

解决方案


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

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

汇编器

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

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

符号文件

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

叠加层

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

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


参考

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


推荐阅读