Как понять такой образец в руководстве GNU ld о скрипте компоновщика?

Я изучаю образец псевдонима области памяти GNU linker ld script.

Я вижу следующий фрагмент сценария ld:

SECTIONS
{
    .text :
    {
        *(.text)
    } > REGION_TEXT

    .rodata :
    {
        *(.rodata)
        rodata_end = .;
    } > REGION_RODATA  <=========== PLACE 1

    .data : AT (rodata_end) <=========== PLACE 2
    {
        data_start = .;
        *(.data)
    } > REGION_DATA <=========== PLACE 3

    data_size = SIZEOF(.data);
    data_load_start = LOADADDR(.data);

    .bss :
    {
        *(.bss)
    } > REGION_BSS
}

Один из возможных макетов области системной памяти, приведенный в примере, выглядит следующим образом (C в этом примере):

MEMORY
    {
        ROM : ORIGIN = 0, LENGTH = 2M            /*0M ~ 2M*/
        ROM2 : ORIGIN = 0x10000000, LENGTH = 1M  /*256M ~ 257M*/
        RAM : ORIGIN = 0x20000000, LENGTH = 1M   /*512M ~ 513M*/
    }

REGION_ALIAS("REGION_TEXT", ROM);     /*0M ~ 2M*/
REGION_ALIAS("REGION_RODATA", ROM2);  /*256M ~ 257M*/
REGION_ALIAS("REGION_DATA", RAM);     /*512M ~ 513M*/
REGION_ALIAS("REGION_BSS", RAM);      /*512M ~ 513M*/

So,

PLACE 1 говорит, что .rodata ДОЛЖЕН перейти в REGION_RODATA, то есть 256M~257M

PLACE 2 говорит, что раздел .data ДОЛЖЕН быть размещен сразу после раздела .rodata. Таким образом, .data раздел ДОЛЖЕН начинаться с максимум 257M.

Но PLACE 3 говорит, что раздел .data ДОЛЖЕН входить в область REGION_DATA. Поэтому .data раздел ДОЛЖЕН начинаться с не менее 512 МБ.

Так как же это могло быть возможно?


person smwikipedia    schedule 11.07.2016    source источник
comment
Можете ли вы связать какой-нибудь пример с этим скриптом и выгрузить из него информацию о разделе с помощью readelf / objdump?   -  person osgx    schedule 11.07.2016


Ответы (1)


Ключевыми понятиями для понимания этого примера являются концепции адреса виртуальной памяти (VMA) и адреса загрузки памяти (LMA).

Официальная документация GNU Linker определяет эти два условия следующим образом.

Каждая загружаемая или выделяемая секция вывода имеет два адреса. Первый - это VMA или адрес виртуальной памяти. Это адрес, который будет иметь секция при запуске выходного файла. Второй - это LMA или адрес загрузочной памяти. Это адрес, по которому будет загружен раздел.

В этом примере для всех выходных секций, кроме .data, адреса VMA и LMA совпадают. Для раздела .data LMA определяется AT (rodata_end), а адрес VMA - это первый доступный адрес REGION_DATA области памяти.

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

ROM (alias REGION_TEXT)
+---------+------------------------------+
|  .text  |                              |
+---------+------------------------------+

ROM2 (alias REGION_RODATA)
+-----------+---------+--------+
|  .rodata  |  .data  |        |
+-----------+---------+--------+

RAM (alias REGION_DATA)
+---------+--------+-----------+
|  .data  |  .bss  |           |
+---------+--------+-----------+

Раздел .data появляется дважды: один раз в ROM2 и один раз в RAM. При загрузке он помещается в свой адрес загрузки (LMA); впоследствии он перемещается на свой виртуальный адрес перед запуском программы. Кстати, вот почему несколькими строчками позже в документации, которую вы упомянули, мы можем прочитать, что

Можно написать обычную процедуру инициализации системы для копирования раздела данных из ПЗУ или ПЗУ2 в ОЗУ, если это необходимо.

person mw215    schedule 12.07.2016
comment
Спасибо. Не могли бы вы помочь разобраться с этим вопросом? Это связано с VMA и LMA и счетчиком местоположения. stackoverflow.com/questions/38341040/ - person smwikipedia; 13.07.2016