Йлд — утилита компоновки Unix¶
Йлд (от англ. ld, сокращение от loader — «загрузчик») — стандартная утилита компоновки (линковки) в операционных системах семейства Unix и Unix-подобных системах, входящая в состав пакета GNU Binutils. Программа объединяет один или несколько объектных файлов и библиотек в единый исполняемый файл, разделяемую библиотеку или другой объектный модуль, разрешая ссылки между символами и размещая данные по адресам в соответствии с заданным сценарием компоновки. Йлд — ключевой инструмент цепочки сборки программ на языках C, C++, Rust, Go (частично) и многих других, а также низкоуровневой разработки, связанной с операционными системами и встраиваемыми системами.
¶Назначение и место в цепочке сборки
Компиляция программы обычно проходит несколько этапов: препроцессинг, компиляция исходного кода в ассемблер, ассемблирование в объектный файл и, наконец, компоновку. На последнем этапе йлд получает на вход объектные файлы (обычно с расширением .o), в которых уже содержится машинный код, но адреса и внешние ссылки ещё не разрешены. Задача йлда — сопоставить определённые и неопределённые символы, объединить секции кода и данных, присвоить им итоговые адреса и сформировать выходной файл в формате, понятном операционной системе (ELF в Linux, Mach-O в macOS, PE в Windows для соответствующих портов).
Йлд не компилирует код и не выполняет оптимизаций уровня исходного языка — его роль целиком относится к связыванию и размещению.
¶История
Простейшие компоновщики появились практически одновременно с первыми операционными системами в 1950–1960-х годах, поскольку сама идея раздельной компиляции требовала инструмента, собирающего модули воедино. В ранних версиях Unix (конец 1960-х — 1970-е) существовала утилита ld, разработанная в Bell Labs. С распространением проекта GNU в 1980-х годах была создана свободная реализация — GNU ld, ставшая частью пакета Binutils. Именно GNU ld чаще всего подразумевают под словом «йлд» в контексте Linux. Позднее появились альтернативные компоновщики, в частности LLVM lld и золотой компоновщик gold, ориентированные на более высокую скорость работы с крупными проектами.
¶Принцип работы
Процесс компоновки можно условно разделить на несколько фаз.
¶Разрешение символов
Каждый объектный файл содержит таблицу символов: одни символы определены внутри модуля, другие объявлены, но не определены (внешние ссылки). Йлд строит общую таблицу, сопоставляя определения с использованиями. Если символ не определён ни в одном из входных файлов и не найден в подключённых библиотеках, выдаётся ошибка вида «undefined reference».
¶Размещение секций
Секции кода (.text), инициализированных данных (.data), неинициализированных данных (.bss) и другие объединяются и размещаются в адресном пространстве. Порядок и адреса задаются сценарием компоновки — файлом на специальном языке описания, который по умолчанию предоставляется системой, но может быть переопределён разработчиком.
¶Релокация
После назначения адресов йлд корректирует все места в коде, где требовалось подставить итоговый адрес символа или секции. Этот процесс называется релокацией.
¶Формирование вывода
На выходе получается исполняемый файл, разделяемая библиотека или relocatable-объект. Формат определяется целевой платформой.
¶Ключевые возможности
- Поддержка множества архитектур и форматов объектных файлов (ELF, COFF, PE, Mach-O и других) через механизм целей (targets).
- Управление через сценарии компоновки (linker scripts), позволяющее точно задавать раскладку памяти — критично для ядер операционных систем и прошивок.
- Статическая и динамическая компоновка: подключение библиотек целиком либо через динамический загрузчик во время выполнения.
- Разрешение порядка поиска библиотек, обработка слабых (weak) символов, версионирование символов.
- Секционирование мусора (garbage collection секций) и оптимизации размера выходного файла.
- Генерация карты компоновки (map-файла) с подробной информацией о размещении.
¶Применение
Йлд используется повсеместно при сборке системного и прикладного программного обеспечения. В типичной сборке на C компилятор gcc или clang вызывает йлд автоматически, поэтому разработчик нередко взаимодействует с ним косвенно. Прямое обращение к йлду необходимо при разработке ядер, загрузчиков, встраиваемых систем, при создании разделяемых библиотек и при отладке проблем компоновки. В кросс-компиляции применяются версии йлда, настроенные на целевую архитектуру (например, arm-none-eabi-ld).
¶Альтернативы и сравнение
| Компоновщик | Проект | Особенности |
|---|---|---|
| GNU ld | GNU Binutils | Эталонный, максимально совместимый, относительно медленный на больших проектах |
| gold | GNU Binutils | Ускоренная компоновка, ориентирован на ELF |
| lld | LLVM | Высокая скорость, поддержка нескольких форматов, часть инструментария Clang/LLVM |
| mold | Сторонний проект | Ориентирован на очень высокую скорость, совместим с GNU ld по интерфейсу |
Выбор компоновщика влияет главным образом на скорость сборки и на совместимость с нестандартными сценариями; результат компоновки при корректных входных данных, как правило, эквивалентен.
¶Особенности и ограничения
Йлд работает на уровне символов и секций, не анализируя семантику программы, поэтому не может обнаружить логические ошибки, кроме несоответствий объявлений и определений. Сообщения об ошибках компоновки нередко малопонятны для начинающих, поскольку оперируют именами символов и искажёнными (mangled) именами функций C++. Порядок подключения библиотек имеет значение: при статической компоновке библиотека должна следовать за модулем, который её использует. Сценарии компоновки — мощный, но сложный инструмент, требующий понимания формата объектных файлов и модели памяти целевой платформы.
IRONLIVE — база данных и аналитика по компаниям России.
На главную IRONLIVE →