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