我将一些代码(汇编和C的混合)编译成ELF二进制文件,QEMU中的某些固件/引导加载程序代码加载到特定的物理地址。 ELF使用虚拟地址链接;但是,代码是在关闭MMU的情况下运行的,这意味着它需要与位置无关。
问题是PC被设置为入口点的物理地址,这是有道理的,但由于所有符号都是使用虚拟地址引用的,因此GDB不知道入口点在哪里。
我仍然可以在MMU打开时调用的函数上设置断点(因此PC将在那时处理虚拟地址),但这不足以调试早期代码,包括单步执行它。
我已经能够通过使用物理地址链接来调试此代码,但显然这会在我打开MMU时立即产生问题。
有谁知道我在这里缺少什么?
我不认为您的问题特别针对QEMU(甚至是ARM)。我相信至少有三种方法可以解决这个问题,
symbol-file
我有这个问题,但只会切换到检查汇编程序。如果您使用MMU /普通地址版本objdump -S
来匹配汇编程序,这是相当容易的。您可以将objdump输出传递给文件,并根据需要删除未重定位的代码。但是,大多数编辑器都能够处理大文件。
查看汇编程序可能非常有用,因为通常某种重定位常量或非PIC类型引用不正确。您需要两个代码/数据都是正确的,并且您的PIC代码可能会调用一些gcc库例程链接到您未考虑的某个位置。因此虽然这是原始的,但它确实有一些优点。
另一种方法是使用symbol-file
所拥有的。在启动期间使用symbol-file
的物理链接,然后在MMU切换后使用MMU /普通链接的symbol-file
。显然加载MMU版本。
我认为你可以用overlays处理这个问题,尽管你实际上正在做反向。 VMA是MMU地址,LMA是物理引导地址。将其标记为最初映射,然后在打开MMU时可以使用_ovly_debug_event()
进行更新。
覆盖采用代码,但它是最方便的。如果您已经在软件开发系统中拥有“调试”构建目标并对该代码进行了条件化,我会尝试这样做。但是,如果您在ld
中使用实际叠加层,它实际上可能会解决您的一些问题,您可能会发现它最强大。覆盖资源影响非常小,但它存在。
这些参考文献是关于为什么要调试它的编码问题。