Я искал повсюду, как это сделать, и не смог найти ответ.
Моя схема памяти выглядит следующим образом:
Fake Address | Section
0 | text
7 | relocate
15 | bss
23 | stack
В конце стека я кладу кучу. Который растет, и стек является полным нисходящим стеком для чипа ARM, который я использую.
Теперь, что я хочу сделать, это разместить один раздел, давайте назовем его .persist
в моей оперативной памяти. Я хочу, чтобы он находился в самом конце ОЗУ, и я хочу запрограммировать это в свой скрипт компоновщика. Тем не менее, это .persist
Размер раздела не определен мной, но вычисляется компилятором из символов, которые он содержит.
До сих пор я не нашел хороший способ сделать это. Так как я знаю начальный адрес ОЗУ и РАЗМЕР, было бы тривиально вычислить, куда должен идти раздел, если бы я знал размер раздела. Однако согласно документация компоновщика GNU (стр. 74) Кажется, что:
SIZEOF (раздел) Возвращает размер в байтах именованного
раздел, если этот раздел был выделен.
Если раздел не был выделен при оценке, компоновщик будет
сообщить об ошибке.
поэтому я не могу определить размер раздела в скрипте компоновщика (так как я хочу вычислить размер ДО того, как я его разместу / выделю).
Кто-нибудь знает хороший способ сделать это?
Я смог сделать нечто подобное, связав процесс в два этапа.
Сначала я компилирую рассматриваемый раздел в его собственный объектный файл. В моем случае у меня был раздел метаданных, созданный из файла сборки. 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
из объектного файла, и я могу ссылаться на его размер в сценарии компоновщика.
У меня была похожая проблема
Я сделал это так
/* 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
то, что я хочу сделать, это поместить один раздел, назовем его .persist, в мою оперативную память. Я хочу, чтобы он находился в самом конце ОЗУ, и я хочу запрограммировать это в свой скрипт компоновщика.
В скрипте компоновщика есть специальная переменная, которая называется Счетчик местоположения который позволяет изменить текущий адрес и, соответственно, размер или адрес раздела или символа, создавая пробелы или дыры в адресном пространстве.
Вы можете заставить разделы в определенных местах.
Например, в этой документации Red Hat GNU Linker страница, Вы можете определить раздел .data для запуска по адресу 0x8000000:
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}