Для понимания почему FreeBSD использует формат elf(5), вам
потребуется сначала немного узнать о трех ``доминирующих'' исполняемых форматах для UNIX®:
-
a.out(5)
Старейший и ``классический'' объектный формат UNIX. Он
использует короткий и компактный заголовок с магическим числом в начале, которое часто
используется для описания формата (смотрите a.out(5) с более
подробной информацией). Он содержит три загружаемых сегмента: .text, .data и .bss плюс
таблицу символов и таблицу строк.
-
COFF
Объектный формат SVR3. Заголовок включает таблицу разделов, так что могут быть
сегменты кроме .text, .data и .bss.
-
elf(5)
Наследник формата COFF, поддерживающий
множественные сегменты и 32-битные или 64-битные значения. Одно важное замечание:
ELF был разработан в предположении что есть только по
одному ABI на одну архитектуру. Это предположение совершенно не верно, и не только в мире
коммерческих SYSV (в котором есть как минимум три ABI: SVR4, Solaris, SCO).
FreeBSD пытается обойти эту проблему, в частности предоставляя утилиту для оглавления известного исполняемого файла
ELF информацией об ABI с которым он совместим.
Обратитесь к странице справочника brandelf(1) за более
подробной информацией.
FreeBSD имеет произошла из ``классического'' лагеря и использовала формат a.out(5), технологию
опробованную и проверенную на многих поколениях релизов BSD, до начала ветки 3.X. Хотя
собирать и запускать родные бинарные файлы ELF (и
ядро) в системе FreeBSD можно было несколько раньше, FreeBSD вначале сопротивлялась
``проталкиванию'' ELF как формата по умолчанию.
Почему? Когда лагерь Linux производил болезненный переход к ELF, у него не было большого преимущества перед исполняемым
форматом a.out, из-за негибкого, основанного на таблице
переходов механизма разделяемых библиотек, что делало создание разделяемых библиотек
очень трудным для поставщиков и разработчиков. Когда доступные инструменты ELF предоставили решение проблемы разделяемых библиотек, и
появилась некоторая перспектива, цена перехода была признана допустимой и он был сделан.
Механизм разделяемых библиотек FreeBSD близок по стилю к механизму разделяемых библиотек
SunOS™ от Sun, и поэтому очень прост в
использовании.
Итак, почему так много разных форматов?
Давно, в темном далеком прошлом, оборудование было простым. Это простое оборудование
поддерживало простые, маленькие системы. a.out был совершенно
адекватен задаче представления бинарных файлов на таких простых системах (PDP-11). Люди,
портировавшие UNIX с этих простых систем, оставили a.out формат потому, что он был достаточен для ранних портов UNIX на архитектуры подобные Motorola 68k, VAXen, etc.
Затем какой-то смышленый инженер по оборудованию решил что если он сможет заставить
программы исполнять некоторые трюки, то сможет несколько упростить дизайн и заставить
ядро CPU работать быстрее. Хотя это было сделано с новым типом оборудования (известного
сейчас как RISC), формат a.out не подходил для него, и было разработано множество форматов
чтобы получить лучшую производительность на таком оборудовании по сравнению с той,
которую мог предоставить простой формат a.out. Были изобретены
форматы COFF, ECOFF
и некоторые другие малоизвестные форматы, и их ограничения были учтены когда все похоже
остановились на ELF.
Кроме того, размеры программ стали огромны, а диски (и оперативная память) остались
относительно малы, поэтому появилась концепция разделяемых библиотек. Система VM также
стала более сложной. Хотя все эти усовершенствования были выполнены с форматом a.out, его полезность все больше и больше уменьшалась с каждым
нововведением. К тому же потребовалась динамическая загрузка во время выполнения, или
выгрузка частей программы после выполнения стартового кода для экономии памяти или места
на диске. Языки усложнялись и потребовался автоматический вызов кода перед главной
программой. Множество изменений было внесено в формат a.out
чтобы все это появилось и в основном работало некоторое время. Настал момент, когда a.out не смог решить все эти проблемы без чрезмерного увеличения
размера и сложности. В то время как ELF решил многие
из этих проблем, перевод этого формата с системы на систему болезненен. Поэтому формату
ELF пришлось подождать пока не стало более болезненным
оставаться с a.out чем перейти на ELF.
Тем временем, инструменты разработки, от которых произошли инструменты разработки
FreeBSD (особенно ассемблер и загрузчик) развивались в двух параллельных направлениях.
Направление FreeBSD добавило разделяемые библиотеки и устранило некоторые ошибки. Люди из
GNU, написавшие эти программы, переписали их и добавили простую поддержку сборки
кросскомпиляторов, подключения различных форматов в будущем и так далее. Многим
требовалось собрать кросскомпиляторы для FreeBSD, и это не удалось, поскольку устаревшие
исходные тексты FreeBSD для as и ld
не подходили для этой задачи. Новый набор инструментов GNU (binutils) поддерживает кросскомпилирование, ELF, разделяемые библиотеки, C++, расширения и т.д. В
дополнение, многие поставщики выпустили программы в формате ELF и они хорошо подходят для запуска в FreeBSD.
ELF более выразителен чем a.out позволяет базовой системе быть более гибкой. ELF лучше поддерживается, и предоставляет поддержку
кросскомпиляторов, что важно для многих людей. ELF
может быть немного медленнее чем a.out, но замерить это сложно.
Есть также множество деталей, отличающихся для этих двух форматов, в том как они
отображают страницы, обрабатывают начальный код, и т.д. В этом нет ничего очень важного,
но они различаются. В настоящее время поддержка a.out убрана из
ядра GENERIC, и со временем будет убрана из ядра как только
потребность в запуске старых программ a.out останется в
прошлом.