GCC для ARM - сегмент выходного файла ELF смещен - PullRequest
0 голосов
/ 11 января 2019

Отредактировано, чтобы добавить: Теперь я кросс-пост опубликовал это на сайте 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]

1 Ответ

0 голосов
/ 25 января 2019

то, что вы видите, может быть не тем, что вы ожидаете, но, тем не менее, верно, ИМХО.

ELF был создан для системы V. ОС, поддерживающая виртуальную память, и mmap() (системный вызов для сопоставления содержимого файла в памяти).

Вы смотрите заголовок программы ELF ( не заголовки разделов, см. Ниже). Заголовок программы представляет собой информацию для загрузчика ELF операционной системы (с поддержкой виртуальной памяти) о том, где предполагается mmap() (полный) файл ELF в виртуальную память, которую он подготовил как образ процесса. Затем эта ОС просто выделит одну (или более) страницу (-ы) где-нибудь, вызовет это (виртуальное) 0x10000 (для этого процесса), отобразит файл и перейдет к 0x10080 (точка входа).

Для вашего второго примера это не будет работать, так как вы указали (виртуальный) начальный адрес до конца заголовка файла ELF (заголовок ELF + заголовок программы + заголовки разделов), так что он не может просто сопоставить файл с границей страницы, что делает его более сложным (или даже невозможным) для ОС, чтобы выполнить его mmap() трюк.

Для вашей «голой железной» ОС (которая, скорее всего, не поддерживает виртуальную память, по крайней мере, при запуске), информация заголовка программы ELF, вероятно, совершенно неактуальна.

Вам, вероятно, лучше вместо этого взглянуть на заголовки разделов. Они описывают физическую память.

...