Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПО юнита 2.doc
Скачиваний:
38
Добавлен:
17.11.2019
Размер:
5.82 Mб
Скачать

3.4 Выходная секция

Можно потребовать, чтобы начальный виртуальный адрес выходной секции был бы выравнен на границу n байт, где n есть степень 2. Это достигается использованием в предложении SECTIONS, на месте адреса, функции ALIGN.

Алгоритм размещения секций для редактора связей ld(1):

– в одну выходную секцию помещаются все входные секции .init, а за ними все входные секции .text. Эта выходная секция получает имя .text; она связывается с адресом, равным 0x0 плюс размер всех заголовков выходного файла;

– все входные секции .data помещаются в одну выходную. Этой выходной секции дается имя .data. В системах со страничной виртуальной памятью она связывается с адресом, который получается выравниванием на машинно-зависимую границу плюс величина, определяемая размерами заголовков и секции .text;

– все секции неинициализированных данных .bss, а также все неинициализированные и неразмещаемые глобальные имена помещаются в одну выходную секцию с именем .bss, которая располагается сразу после секции .data без выравнивания по какой-либо границе.

Этот алгоритм не применяется, если во входном потоке есть хотя бы одно предложение SECTIONS. В случае самостоятельной обработки объектных файлов обычного формата можно извлечь информацию об адресах и порядке следования секций из заголовков файла и его секций. Подразумеваемый алгоритм размещения эквивалентен следующему предложению:

SECTIONS {

.text размер_заголовков : { *(.init) *(.text) }

}

GROUP BIND (NEXT (граница_выравнивания) +

(SIZEOF (.text) + ADDR (.text)) % 0x2000) : {

.data : { }

.bss : { }

}

}

где граница_выравнивания – машинно-зависимая константа. Предложение GROUP обеспечивает группировку, то есть последовательное размещение двух выходных секций .data и .bss. Связывание с конкретным адресом и выравнивание по определенной границе производится для группы в целом, а не для отдельных входящих в нее секций. Секции, образующие группу, размещаются последовательно в том порядке, в котором они указываются в предложении GROUP.

Если необходимо сгруппировать секции .text, .data и .bss, следует использовать такое предложение SECTIONS:

SECTIONS {

GROUP: {

.text: {}

.data: {}

.bss: {}

} }

При этом выходной файл будет по-прежнему содержать три различные секции (.text, .data и .bss). Однако они будут размещаться в последовательных участках виртуальной памяти.

Группу выходных секций как единое целое можно связать с конкретным адресом или произвести ее выравнивание на определенную границу, указав нужный адрес в предложении GROUP. Так, для связывания с адресом 0xС0000 достаточно воспользоваться конструкцией

GROUP 0xС0000: {

а для выравнивания на границу, кратную 0x10000, – конструкцией

GROUP ALIGN (0x10000): {

Если предложение GROUP не используется, то каждая выходная секция рассматривается отдельно:

SECTIONS {

.text: {}

.data ALIGN (0x2000): {}

.bss: {}

}

Секция .text связывается с виртуальным адресом 0x0, если он находится в пределах конфигурируемой памяти. Секция .data связывается с виртуальным адресом, кратным 0x2000. Если хватит места, секция .bss будет следовать сразу за секцией .text, если же не хватит – то сразу за секцией .data. Порядок, в котором имена выходных секций появляются в предложении SECTIONS, не определяет порядка следования этих секций в выходном файле.

Специальный символ точка может появляться только в предложениях определения секций и в операторах присваивания. Его появление в левой части оператора присваивания предписывает ld(1) увеличить или переустановить счетчик размещения, что приводит к образованию пустого места в выходной секции. Отметим, что для таких пустот физически отводится место в выходном файле. Они инициализируются с помощью заполнителя – подразумеваемого (0x00) или явно указанного.

Рассмотрим следующее определение секции:

outsec: {

. += 0x1000;

f1.o (.text)

. += 0x100;

f2.o (.text)

. = align (4);

f3.o (.text)

}

Результат выполнения этого предложения:

– в начале секции окажется "дыра" длиной 0x1000 байт, инициализированная с помощью подразумеваемого заполнителя. Затем будет следовать входная секция .text из файла f1.o;

– через 0x100 байт после окончания f1.o(.text) окажется входная секция .text из файла f2.o;

– секция .text из файла f3.o будет размещена с ближайшей границы слова вслед за секцией .text из файла f2.o. Выравнивание производится относительно начала секции outsec.

Размещение и выравнивание в пределах одной выходной секции производится относительно ее начала, то есть так, как если бы секция начиналась с нулевого адреса. Поэтому если в рассмотренном выше примере адрес выходной секции outsec окажется нечетным, то нечетным будет и адрес той части outsec, куда размещается входная секция f3.o (.text), даже если f3.o (.text) и была ранее выравнена на границу слова. Этого можно избежать, потребовав выравнивания выходной секции в целом:

outsec ALIGN (4): {

Заметим, что ассемблер as(1) всегда производит выравнивание генерируемых им секций на границу слова, так что можно не указывать это требование явно.

Операторы, уменьшающие счетчик размещения, являются некорректными, поскольку повторное размещение по какому-либо адресу не допускается. Как правило, для изменения счетчика размещения используются операции += и align.