Вот есть две записи:
Код
.text . : { *(.text) }
.text : { *(.text) }
.text : { *(.text) }
В первой адрес указывается явно через location counter, во второй записи явного указания адреса нет, но он тоже вычисляется через location counter. Для второго случая написано, что при этом учитываются требования к выравниванию, заданные во входных секциях. Не совсем понятно, как эти правила задаются в С программе. Как, например, задать выравнивание для секции .bss или .data?
Из этого вопроса следует следующий - где вообще принято устанавливать правила выравнивания для секций - в коде программы или в скриптах линкера?
Вот кусок из дефолтового скрипта для AVR32:
Код
.text :
{
*(.text)
} >FLASH AT>FLASH :FLASH =0xd703d703
.lalign : { . = ALIGN(8); PROVIDE(_data_lma = .); } >FLASH AT>FLASH :FLASH
. = ORIGIN(INTRAM);
.data :
{
*(.data)
} >INTRAM AT>FLASH :INTRAM_AT_FLASH
{
*(.text)
} >FLASH AT>FLASH :FLASH =0xd703d703
.lalign : { . = ALIGN(8); PROVIDE(_data_lma = .); } >FLASH AT>FLASH :FLASH
. = ORIGIN(INTRAM);
.data :
{
*(.data)
} >INTRAM AT>FLASH :INTRAM_AT_FLASH
Получается, чтобы выровнять LMA адрес для секции .data создается специальная секция-прослойка .lalign, а затем по команде AT>FLASH секция .data попадает во flash с нужным выравниванием.
Т.е. секция .data во флеш памяти должна быть расположена строго после секции .lalign, только тогда будет гарантировано ее правильное выравнивание.
На мой взгляд, такой подход противоречит идеологии линкера - секции независимы, главное, что функции из одной секции могут обращаться к функциям другой секции по адресам.
Но с другой стороны сохраняется возможность в коде задать выравнивание больше, чем 8 (8 задано в секции lalign ) и секция разместится правильно, так как AT>FLASH привязана к location counter с учетом выравнивания из входных секций.
LMA адрес для секции можно задать по другому:
Код
.text :
{
*(.text)
} >FLASH :FLASH =0xd703d703
PROVIDE(_data_lma = ALIGN(8));
. = ORIGIN(INTRAM);
.data ALIGN(8) :
AT(_data_lma)
{
*(.data)
} >INTRAM :INTRAM_AT_FLASH
{
*(.text)
} >FLASH :FLASH =0xd703d703
PROVIDE(_data_lma = ALIGN(8));
. = ORIGIN(INTRAM);
.data ALIGN(8) :
AT(_data_lma)
{
*(.data)
} >INTRAM :INTRAM_AT_FLASH
Но насколько я понимаю, в этом случае адрес для размещения _data_lma указывается в явном виде, и все возможные требования по выравниванию, заданные в исходниках, будут проигнорированы.
Ну и еще раз повторю вопрос - где обычно задают выравнивание для секций - в исходниках (С и asm) или в скрипте линкера? Если в исходниках, то по хорошему его надо задавать для всех секций, даже для .data и .bss? А то получается, например, что в стартапе .data копируется в RAM двойными словами, т.е. и VMA и LMA для нее должны быть обязательно выровнены на 8 ( в этом случае это задается в скрипте линкера). А есть другие секции, где выравнивание задается в исходниках, и если в линкере указать явный адрес, то выравнивание из исходников будет проигнорировано, причем без всяких warning.