Отредактировано, чтобы добавить: Теперь я кросс-пост опубликовал это на сайте GNU ARM Embedded Toolchain , так как я совершенно уверен, что это ошибка компоновщика.
Кроме того, я заметил, что, похоже, это происходит, когда первый программный сегмент помещается на первой странице в файле ELF (то есть его начальное смещение на этой странице>> число байтов в заголовке ELF). В этом случае сегмент ошибочно расширяется вниз до начала файла. Это объясняет, почему проблема исчезает, если смещение начального адреса на странице уменьшается с 0x80 до 0x40.
Я внедряю автономную ОС для ARM Cortex M0, и у меня странная проблема с компоновщиком. Вот мой исходный файл OS.c
, урезанный для иллюстрации проблемы:
int EntryPoint (void) { return 99 ; }
А вот мой файл сценария компоновщика OS.ld
, просто назначающий весь код области, начиная с 0x10080
:
MEMORY
{
NVM (rx) : ORIGIN = 0x10080, LENGTH = 0x1000
}
SECTIONS
{
.text 0x10080 :
{
OS.o (.text)
} > NVM
}
Я компилирую и связываю это:
arm-none-eabi-gcc.exe -march=armv6-m -mthumb -c OS.c
arm-none-eabi-gcc.exe -oOS.elf -Xlinker --script=OS.ld OS.o -nostartfiles -nodefaultlibs
И теперь, когда я перечисляю сегменты программы с помощью readelf OS.elf -l
, я получаю:
Elf file type is EXEC (Executable file)
Entry point 0x10080
There are 1 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00010000 0x00010000 0x0008c 0x0008c R E 0x10000
В соответствии с этим, единственный и единственный сегмент программы начинается со смещения 0x000000
в выходном файле ELF, что является сумасшествием: эта область содержит информацию заголовка ELF, не относящуюся к ОС. И физический начальный адрес - 0x00010000
, которого нет в моем оборудовании.
Но странная вещь заключается в том, что если я изменю оба экземпляра 0x10080
на 0x10040
в файле сценария компоновщика, это сработает! Я получаю:
Elf file type is EXEC (Executable file)
Entry point 0x10040
There are 1 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010040 0x00010040 0x00010040 0x0000c 0x0000c R E 0x10000
Теперь сегмент программы находится в нужном месте в файле и имеет длину 0x0000c
вместо 0x0008c
. К сожалению, адрес 0x00010040
не существует в моем оборудовании, поэтому это не решение.
Это ошибка в компиляторе GCC ARM? Запуск с --version
дает:
arm-none-eabi-gcc.exe (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]