Linker Script - Размещение раздела в конце области памяти

Я искал далеко и широко, как это сделать, и не смог ответить.

Мой макет памяти выглядит следующим образом:

Fake Address | Section
     0       |  text
     7       |  relocate
    15       |  bss
    23       |  stack

В конце стека я помещаю кучу. Который растет, а стек - полный нисходящий стек для используемого чипа ARM.

Теперь то, что я хочу сделать, это разместить один раздел, называть его .persist, в мою память RAM. Я хочу, чтобы он находился в самом конце ОЗУ, и я хочу запрограммировать это в моем компоновщике script. Однако этот размер .persist не определяется мной, а вычисляется компилятором из содержащихся в нем символов.

До сих пор у меня не было хорошего способа сделать это. Поскольку я знаю начальный адрес RAM и SIZE, было бы тривиально рассчитать, где раздел должен идти, если бы я знал размер раздела. Однако, согласно документации по компоновщику GNU (стр. 74), кажется, что:

SIZEOF (раздел) Возвращает размер в байтах имени если этот раздел был выделен. Если раздел не был выделен при оценке, компоновщик будет сообщите об ошибке.

поэтому я не могу определить размер раздела в компоновщике script (так как я хочу рассчитать размер до того, как поместить его/выделить).

Кто-нибудь знает хороший способ сделать это?

Ответ 1

Я смог выполнить что-то подобное, сделав ссылку на двухэтапный процесс. Сначала я компилирую рассматриваемый раздел в свой собственный объектный файл. В моем случае у меня был раздел метаданных, сгенерированный из файла сборки. gcc -c будет компилировать исходный код в объектные файлы, но не связывать их.

gcc -c  metadata.s  -o metadata.o

Вы также можете создать свою всю программу, а затем извлечь только раздел, о котором идет речь, с помощью objcopy.

gcc -c  main.cc  -o main.o
objcopy --only-section=.metadata  main.o  metadata.o

Теперь я создаю и связываю остальную часть программы и включаю в нее объектный файл.

gcc metadata.o  ../main.o  -o Program.elf  -T linkerscript.ld   

Компонент читает раздел .metadata из объектного файла, и я могу ссылаться на его размер в компоновщике script.

Ответ 2

то, что я хочу сделать, это разместить один раздел, позвольте ему перенести его в память RAM. Я хочу, чтобы он находился в самом конце ОЗУ, и я хочу запрограммировать это в моем компоновщике script.

У компоновщика script есть специальная переменная, называемая счетчик местоположений, которая позволяет изменить текущий адрес и, таким образом, размер или адрес раздела или символом, создавая промежутки или отверстия в адресном пространстве.

Ответ 3

Вы можете форматировать секции в определенных местах.

Например, в этой документации Red Hat GNU Linker страница вы можете определить раздел .data для начала по адресу 0x8000000:

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}

Ответ 4

У меня была аналогичная проблема Я сделал это таким образом

/* heap section */
.heap (NOLOAD):
{
    . = ALIGN(8);
     _sheap = .;
    . = . + HEAP_SIZE;
    . = ALIGN(8);
    _eheap = .;
} > ram

_ram_end_ = ORIGIN(ram) + LENGTH(ram) -1 ;
_stack_size = _ram_end_ - _eheap ;

/* stack section */
.stack (NOLOAD): 
{
    . = ALIGN(8);
    _sstack = .;
    . = . + _stack_size;
    . = ALIGN(8);
    _estack = .;
} > ram

.LastSection (NOLOAD): /* for test in dump file */
{
    . = ALIGN(8);
} > ram