c - 在 QEMU 中调试早期内核启动代码
问题描述
我有一些代码(汇编和 C 的混合)编译成 ELF 二进制文件,QEMU 中的一些固件/引导加载程序代码加载到特定的物理地址。ELF 使用虚拟地址链接;但是,代码是在 MMU 关闭的情况下运行的,这意味着它需要与位置无关。
问题是 PC 被设置为入口点的物理地址,这是有道理的,但由于所有符号都是使用虚拟地址引用的,所以 GDB 不知道入口点在哪里。
我仍然可以在打开 MMU 时调用的函数上设置断点(因此此时 PC 将处理虚拟地址),但这不足以调试早期代码,包括单步执行它。
我已经能够通过使用物理地址链接它来调试此代码,但显然这将在我打开 MMU 时产生问题。
有谁知道我在这里想念什么?
解决方案
我认为您的问题不是 QEMU(甚至 ARM)所特有的。我相信至少有三种方法可以解决这个问题,
- 只需使用汇编程序
- 利用
symbol-file
- 叠加层
汇编器
我有这个问题,但只是切换到检查汇编程序。这相当容易,特别是如果您objdump -S
使用 MMU/普通地址版本来匹配汇编器。如果需要,您可以将 objdump 输出通过管道传输到文件并删除未重定位的代码。但是,大多数编辑器将能够处理大文件。
查看汇编程序可能会很有帮助,因为某种重定位常量或非 PIC 类型引用通常是不正确的。您需要代码/数据都是正确的,并且您的 PIC 代码可能会调用一些 gcc 库例程,这些例程链接到您没有考虑到的某个地方。所以虽然这很原始,但它确实有一些优势。
符号文件
另一种方法是使用你所拥有的symbol-file
. 在引导期间使用物理链路,symbol-file
然后symbol-file
在 MMU 切换后使用 MMU/正常链路。显然加载MMU版本。
叠加层
我认为你可以用覆盖来处理这个问题,尽管你实际上是在做一个逆操作。VMA 是 MMU 地址,LMA 是物理引导地址。最初将其标记为已映射,然后您可以_ovly_debug_event()
在打开 MMU 时进行更新。
叠加层采用代码,但它是最方便的。如果您的软件开发系统中已经有一个“调试”构建目标并对该代码进行条件化,我会尝试这样做。但是,如果您在 中使用实际覆盖ld
,它实际上可能会解决您的一些问题,您可能会发现这是最强大的。覆盖资源的影响非常小,但它确实存在。
参考
- 如何在 ARM 上从 RAM 运行代码- 与 MMU/非 MMU 类似的问题。
- ARM 汇编器中的重定位- 用于获取偏移量(以调整指针)的代码。
参考是关于为什么您可能要调试它的编码问题。
推荐阅读
- reactjs - Next.js 添加 slug/params 以清理 URL
- java - 如何使用 OnTouch 移动事件将 Android Studio 中的 ImageView 旋转到中心点?
- php - 使用服务器端时搜索和分页不起作用
- jquery - 如何获取按钮的onClick行的索引?
- python - 如何使用 Pandas 获得日期时间的累计值?
- java - 错误:未能读取输入对象(不是模板?):将 YAML 转换为 JSON 时出错:yaml:在此上下文中不允许映射值
- python - Django 在查询结果中加入多个模型
- sql - SQL - 在其后的行中选择具有特定列值的行
- python - Flask POST Redirect:地址栏中显示的参数
- google-cloud-dataflow - 可以在 Apache Beam 中使用 for 循环进行步进顺序吗