Открыть сервис

Йлд — утилита компоновки 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 ldGNU BinutilsЭталонный, максимально совместимый, относительно медленный на больших проектах
goldGNU BinutilsУскоренная компоновка, ориентирован на ELF
lldLLVMВысокая скорость, поддержка нескольких форматов, часть инструментария Clang/LLVM
moldСторонний проектОриентирован на очень высокую скорость, совместим с GNU ld по интерфейсу

Выбор компоновщика влияет главным образом на скорость сборки и на совместимость с нестандартными сценариями; результат компоновки при корректных входных данных, как правило, эквивалентен.

Особенности и ограничения

Йлд работает на уровне символов и секций, не анализируя семантику программы, поэтому не может обнаружить логические ошибки, кроме несоответствий объявлений и определений. Сообщения об ошибках компоновки нередко малопонятны для начинающих, поскольку оперируют именами символов и искажёнными (mangled) именами функций C++. Порядок подключения библиотек имеет значение: при статической компоновке библиотека должна следовать за модулем, который её использует. Сценарии компоновки — мощный, но сложный инструмент, требующий понимания формата объектных файлов и модели памяти целевой платформы.

IRONLIVE — база данных и аналитика по компаниям России.

На главную IRONLIVE →