Перейти к содержанию

LINK148

LINK148 (Cawas Linker for i80148) - компоновщик, который собирает объектные файлы .o и статические библиотеки .a в единый плоский бинарник .bin + .hex.

Параметр Значение
Версия 0.1
Целевая архитектура i80148 (32-бит, flat)
Порядок байтов Big Endian
Вход .o (binary/JSON), .a, .ld
Выход .bin + .hex
Файл LINK148.py

Использование

# Простая сборка из объектных файлов
python LINK148.py startup.o main.o -o program.bin --entry _start

# С библиотекой
python LINK148.py startup.o main.o libio.a -o program.bin --entry _start

# С собственным скриптом линковки
python LINK148.py -T program.ld startup.o main.o -o program.bin
Опция Описание
-o file Выходной бинарник (по умолчанию output.bin)
-T file Скрипт линковки
--base addr Базовый адрес для дефолтной раскладки
--entry SYM Переопределить точку входа

Скрипт линковки можно передавать без -T - достаточно, чтобы имя заканчивалось на .ld.

Порядок разрешения точки входа

  1. ENTRY(symbol) в скрипте линковки.
  2. --entry в командной строке.
  3. Поле .entry в первом объектном файле.
  4. Символ _start по умолчанию.

Объектный формат

Объектный файл версии 1 содержит:

Часть Размер Описание
Header 64 B Магия CWO\0, версия, архитектура, размеры, смещение данных, имя entry
Section headers 32 B × n Имя, тип, адрес, размер, смещение данных
Symbol table 48 B × n Имя, индекс секции, смещение, флаги
Relocation table 48 B × n Имя, индекс секции, смещение, тип, pc_after
Section data var Сырые байты для text/data, для bss - только размер
  • Все многобайтовые поля - big-endian.
  • Индекс секции 0xFFFFFFFF означает неопределённый (внешний) символ.
  • Флаг символа: бит 0 - глобальный.

Секции

Имя Назначение
text Код
data Инициализированные данные
bss Нулевые данные (только размер)

Типы релокаций

Тип Описание
abs32 Абсолютный 32-битный адрес
rel32 PC-относительное 32-битное смещение
  • rel32 используется для CALL и JMP.
  • abs32 - для LDI.DW и плоских адресов в STR/LOD.

Разрешение символов

  1. Каждый объектный файл отдаёт свои .global символы в общую таблицу.
  2. Релокация сначала ищется в локальных символах объекта.
  3. Если не найдена - в глобальной таблице.
  4. Архивы (.a) сканируются итеративно, пока не перестанут появляться новые определённые символы.

Раскладка по умолчанию

Без скрипта секции располагаются подряд от --base:

text  по адресу base
data  сразу после text
bss   сразу после data

Скрипт линковки

Поддерживаются комментарии // и /* */.

Синтаксис

Элемент Описание
ENTRY(symbol); Объявить точку входа
SECTIONS { ... } Определить выходные секции
symbol = expr; Определить символ
. = expr; Установить текущий location counter
.name [addr] : { *(input...) } Слить входные секции в выходную

Выражения

Символ Описание
number Число (dec или 0x...)
. Текущий адрес
+ - * / Арифметика
ALIGN(n) Выровнять адрес на n байт
SIZEOF(.name) Размер выходной секции

Пример

ENTRY(_start);

SECTIONS
{
    . = 0x00060000;
    .text : { *(.text) }
    .data : { *(.data) }
    .bss  : { *(.bss) }
}

Имена входных секций можно писать без ведущей точки.

Runtime-символы

Линкер автоматически определяет:

Символ Описание
_DATA_START Адрес .data
_DATA_END Конец .data
_BSS_START Адрес .bss
_BSS_END Конец .bss
_END Конец .bss

Архивный формат

Статические библиотеки .a создаются через AR148. Формат архива версии 1:

Поле Размер Описание
Magic 4 B CWA\0
Version 4 B 1 (big-endian)
Count 4 B Число членов
Reserved 4 B Нули
Member headers 40 B × n Имя + смещение + размер
Member data var Сырые данные

Члены архива могут быть бинарными (CWO\0) или JSON-объектами.

Пример

$ python LINK148.py startup.o main.o libio.a -o program.bin --entry _start
Linked 1024 bytes
Sections: text=0x00060000 (512 bytes), data=0x00050200 (256 bytes), bss=0x00050300 (256 bytes)
Global symbols: {_START, _DATA_START, _DATA_END, _BSS_START, _BSS_END, _END}
Entry point: _START = 0x00060000
Written: program.bin and program.hex