【问题标题】:Bare-metal ARM Cortex-A7 newlib crt0 not initializing .bss and .data regions裸机 ARM Cortex-A7 newlib crt0 未初始化 .bss 和 .data 区域
【发布时间】:2021-05-19 17:33:13
【问题描述】:

我正在学习编写裸机 ARM Cortex-A7 固件,以便在带有半主机的 QEMU 上运行。我知道 ARM GCC 有一个名为 newlib 的 libc 实现,它支持常用 libc 函数的半主机。所以我正在尝试让 newlib 也能正常工作。

解决了很多问题,代码终于在QEMU上正常运行了:https://github.com/iNvEr7/qemu-learn/tree/master/semihosting-newlib

(注意:QEMU 5.2.0 似乎有一个错误会导致 newlib 对 HEAPINFO 的半主机调用崩溃,因此要在 QEMU 上运行我的代码,您必须编译 QEMU master,并使用 make run 目标来运行代码tmux 会话中的 QEMU)

不过,我想为我在与 newlib 集成时遇到的一些问题找到一些答案。

据我了解,newlib 作为一个 libc 实现,提供了一个 crt0 例程来初始化应用程序的内存区域,包括 .bss、.data、堆和堆栈。

但是,根据我的测试,GCC 链接的 crt0 不会初始化 .bss 和 .data 区域,因此会导致后面的 crt0 例程崩溃。

所以我必须为 .bss 和 .data 编写自己的初始化代码,以使其正确运行。

所以我想了解我的做法是否正确?我是否遗漏了一些可以让 newlib 为我初始化这些区域的东西?还是按照惯例自己初始化?

注意:我正在使用 arm-none-eabi-gcc stable 9-2019-q4-major

【问题讨论】:

  • 您确认您链接了 newlib 启动文件并检查了 newlib crt 源,但尽管它没有链接该文件?或者当您检查 newlib 时,它没有初始化 .data 和 .bss 的引导文件? (这是链接器问题还是代码问题)?
  • gcc 不会链接链接器,如果您允许,gcc 会启动链接器,但在这种情况下,您可能希望自己控制链接器。 YMMV 如果您让 gcc 调用链接器,那么您需要确保它正在使用您想要的文件并将其放在正确的位置
  • 引导代码和链接描述文件有着密切的关系,它们是一对/集合(对于那些选择过度复杂化链接描述文件的人(大多数人))
  • @old_timer 我确认链接器链接了一个 crt0 并且通过 dissaembly 它似乎是 newlib crt0 除了它没有 .bss 和 .data 初始化代码。虽然 newlib 源似乎有 init .bss 代码:github.com/bminor/newlib/blob/… 但我没有在 newlib 源中找到 .data 初始化代码。
  • 注解:Cortex-M 的工具链可能不应该使用,而Cortex-A 的工具链应该使用。

标签: gcc arm qemu newlib semihosting


【解决方案1】:

似乎我在 newlib 本身中遇到了一个错误,而我当前的代码由于一些随机的运气而运行良好。

所以我将我的工具链更新为 gcc-arm-none-eabi-10-2020-q4-major 并尝试编译相同的代码。这次又崩溃了。

所以我附加了 GDB 并逐步检查了 ctr0 汇编代码,试图找出原因。

原来this line of code将标签的地址加载到r1,但它应该加载该标签地址中的内容,即ldr r1, .LC0 而不是adr r1, .LC0

这个错字的后果是 heapinfo 半主机调用返回的数据覆盖了该标签之后的其他数据,其中包含有关内存区域的信息。它反过来又影响了 crt0 例程中的 .bss 初始化代码。在我之前使用旧工具链进行的测试中,幸运的是它运行时没有崩溃,但使用最新的工具链,这样的错误会导致致命的崩溃。

我也意识到 5.2.0 QEMU 崩溃也可能是由这个 newlib 错误引起的,而不是 QEMU 问题。不知何故,主 QEMU 版本的行为有所不同,导致崩溃消失。

我已经向 newlib 提交了一个补丁。让我感到惊讶的是,这样一个致命的错误竟然可以在不知不觉中溜走这么多年,而它却可以通过一个简单的 hello world 程序来揭示。

无论如何,我的挖掘似乎也回答了我的问题。如果 newlib 工作正常,它应该已经初始化了 .bss 部分。但是 newlib 中没有代码来初始化 .data 部分,我们必须手动为裸机执行此操作。


情节转折:从 newlib 邮件列表中返回。事实证明,newlib 的实现确实符合 ARM 规范:

https://developer.arm.com/documentation/100863/0300/Semihosting-operations/SYS-HEAPINFO--0x16-?lang=en

其中“参数寄存器包含指向四字段数据块的指针的地址。”

而是 QEMU 做出了误解并写入了错误的地址。将改为向 QEMU 提交问题。

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 2019-03-24
    • 2017-01-21
    • 1970-01-01
    • 2012-05-15
    • 2011-05-14
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    相关资源
    最近更新 更多