Bare-metal ARM Cortex-A7 newlib crt0 не инициализирует регионы .bss и .data

Я учусь писать прошивку ARM Cortex-A7 для работы на QEMU с полухостингом. Я знаю, что в ARM GCC есть реализация libc под названием newlib, которая поддерживает полухостинг для общих функций libc. Итак, я пытаюсь заставить работать newlib.

После решения множества проблем код, наконец, корректно работает в QEMU: https://github.com/iNvEr7/qemu-learn/tree/master/semihosting-newlib

(Примечание: QEMU 5.2.0, похоже, имеет ошибку, которая приведет к сбою вызова полухостинга newlib для HEAPINFO, поэтому для запуска моего кода в QEMU вам нужно скомпилировать мастер QEMU и использовать make run цель для запуска кода с QEMU в сеансе tmux)

Однако я хотел бы найти ответы на некоторые проблемы, с которыми я столкнулся при интеграции с newlib.

Насколько я понимаю, newlib как реализация libc предоставляет подпрограмму crt0, которая инициализирует область памяти приложения, включая .bss, .data, кучу и стек.

Однако, судя по моим тестам, crt0, с которым связан GCC, не инициализирует области .bss и .data и из-за этого приведет к сбою более поздней подпрограммы crt0.

Поэтому мне пришлось написать собственный код инициализации для .bss и .data, чтобы он работал правильно.

Итак, я хочу понять, правильно ли я делаю? Я пропустил что-то, что позволило бы newlib инициализировать эти регионы за меня? Или инициализацию принято делать сам?

Примечание: я использую arm-none-eabi-gcc stable 9-2019-q4-major

1 ответ

Похоже, я обнаружил ошибку в самой newlib, и мой текущий код работает нормально из-за некоторой случайной удачи.

Поэтому я обновил свою цепочку инструментов до gcc-arm-none-eabi-10-2020-q4-major и попытался скомпилировать тот же код. На этот раз снова вылетает.

Итак, я подключил GDB и прошел через ассемблерный код ctr0, пытаясь понять, почему.

Оказывается, эта строка кода загружает адрес метки в r1, но она должна загружать содержимое по адресу этой метки, т.е. ldr r1, .LC0 вместо adr r1, .LC0 .

Следствием этой опечатки является то, что возвращенные данные из вызова полухостинга heapinfo перезаписывают другие данные после этой метки, которые содержат информацию об областях памяти. Это, в свою очередь, повлияло на код инициализации .bss позже в подпрограмме crt0. В моем предыдущем тесте с использованием более старой инструментальной цепочки он, к счастью, работал без сбоев, но с последней инструментальной цепочкой такая ошибка вызывает фатальные сбои.

Я также понял, что сбой 5.2.0 QEMU также может быть вызван этой ошибкой newlib, а не проблемой QEMU. Каким-то образом основная версия QEMU вела себя по-другому, что привело к исчезновению сбоя.

Я отправил патч на newlib. Меня удивило, что такая роковая ошибка может проскользнуть через столько лет без предупреждения, в то время как ее можно выявить с помощью простой программы hello world.

Во всяком случае, похоже, что и на мой вопрос я нашел ответ. Если newlib работал правильно, он должен был инициализировать раздел .bss. Но в newlib нет кода для инициализации раздела .data, и нам приходится делать это вручную для «голого металла».

Другие вопросы по тегам