2013-09-05 3 views
10

Я искал далеко и широко, как это сделать, и не смог найти ответ.Сценарий компоновщика - размещение раздела в конце области памяти

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

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

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

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

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

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

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

Кто-нибудь знает, как это сделать?

+0

У меня есть та же самая проблема. Это вам помогает? http://stackoverflow.com/a/19348569/911550 – parvus

+0

Это частичное решение, но не то, что мне нужно. Это все еще самый близкий кто-то еще помог. Благодаря! – nonsensickle

ответ

0

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

компоновщик скрипт имеет специальную переменную Location Counter, которая позволяет изменять текущий адрес, и в качестве такого размера или адреса секции или символа, путем создания разрывов или отверстий в адресном пространстве.

+0

Да, я знаю об этом. Вы пропустили то, что я сказал после того, как оператор 'SIZEOF' не дал вам размер раздела **, пока ** вы его не поместите *. Мне нужно получить размер раздела ** до ** Я поместил его для этого, чтобы он работал. – nonsensickle

+0

Единственным обходным решением было бы, если бы я мог разместить раздел, получить размер, а затем сместить его и переместить его в другое место ... – nonsensickle

0

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

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

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

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

5

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

+0

Прошло много времени с тех пор, как я в последний раз работал над этим проектом, но ваш ответ кажется самым близким к тому, чтобы это стало возможным. Мне нужно будет проверить его, прежде чем отметка будет корректной, но на данный момент +1. – nonsensickle

0

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

/* 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 
+0

Хотя я и рассматривал этот вопрос, возникает вопрос о размещении секции в конце ram, так что последний байт этого раздела занимает адрес '_ram_end'. Из того, что я вижу, вы помещаете стек в конец бара, и стек просто занимает все оставшиеся байты. Я прошу сделать это с разделом, который, в отличие от стека, имеет статический размер, который не зависит от размеров других разделов. Эффективно, в этом примере ваш стек занимает всю оставшуюся память в ОЗУ. – nonsensickle

Смежные вопросы