Сценарий компоновщика — размещение раздела в конце области памяти

Я искал повсюду, как это сделать, и не смог найти ответ.

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

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

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

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

До сих пор я не нашел хороший способ сделать это. Так как я знаю начальный адрес ОЗУ и РАЗМЕР, было бы тривиально вычислить, куда должен идти раздел, если бы я знал размер раздела. Однако согласно документация компоновщика GNU (стр. 74) Кажется, что:

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

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

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

12

Решение

Я смог сделать нечто подобное, связав процесс в два этапа.
Сначала я компилирую рассматриваемый раздел в его собственный объектный файл. В моем случае у меня был раздел метаданных, созданный из файла сборки. 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 из объектного файла, и я могу ссылаться на его размер в сценарии компоновщика.

5

Другие решения

У меня была похожая проблема
Я сделал это так

/* 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
1

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

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

0

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

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

SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
0
По вопросам рекламы [email protected]