Вопрос или проблема
Я изучаю вопросы перемещения из справочника ELF и этого блога, но не могу понять, как вычислить адрес перемещения.
-
Предположим, у нас есть два файла
A
иB
типаET_REL
, мы хотим объединить их секции под названиемS
во время компоновки; эти секции содержат символыSA
(в файлеA
) иSB
(в файлеB
). Если у нас есть записи для перемещения и смещения перемещения вA.elf
иB.elf
, я не понимаю, как компоновщик избегает конфликта адресов перемещения: я предполагаю, что эти смещения могут быть одинаковыми вA.elf
иB.elf
, так как эти файлы не знают друг о друге во время компиляции. -
Какова цель таблицы перемещения в ET_EXEC? Я не вижу, зачем она нужна.
-
Какова цель добавочного значения в перемещении типа Rela?
Я думаю, что больше всего у меня нет четкого понимания того, как выглядит процесс перемещения, шаг за шагом. В блоге есть пример, но я не понимаю, что именно происходит с этим символом, какой результат и как мы объединяем несколько секций. Буду признателен за любые предложения по ресурсам для изучения.
Я предполагаю, что эти смещения могут быть одинаковыми в A.elf и B.elf, так как эти файлы не знают друг о друге во время компиляции.
Насколько я знаю, для типа ET_REL
адреса секций не устанавливаются. Если вы выполните readelf -S file.o
, вы увидите все нули в колонке Address
. Ситуация меняется для типа ET_EXEC
, для которого вы можете установить начальные адреса секций во время компоновки.
Какова цель таблицы перемещения в ET_EXEC? Я не вижу, зачем она нужна.
Для ET_EXEC
, насколько я знаю, она нужна только для кода PIE. Если вы компонуете с флагом -no-pie
, то таблицы перемещения нет, если только вы не используете флаг --emit-relocs
. Существует 2 различных типа перемещений. ET_REL
содержит перемещения, которые нужны только компоновщику. Компоновщик разрешает и удаляет их все (если не используется --emit-relocs
, в этом случае они не удаляются). Но если используется режим компоновки -pie
, то компоновщик может генерировать другой тип перемещений (например, R_386_RELATIVE
), которые необходимы для динамического компоновщика ld.so – они отсутствуют в ET_REL
, но могут присутствовать в ET_EXEC
.
Какова цель добавочного значения в перемещении типа Rela?
Цель такая же, как и в REL, за исключением того, что в случае RELA добавочное значение хранится в самой таблице перемещений. Я думаю, что разница в основном структурная, и скорее всего существуют нетехнические (исторические) причины, почему оба типа существуют. В большинстве (или всех?) случаев достаточно любого из них.
Ответ или решение
Ответ на вопрос о вычислении адреса релокации в формате ELF
1. Отсутствие конфликтов адресов релокации при слиянии файлов ET_REL
Когда мы работаем с файлами типа ET_REL, как файлы A и B в вашем примере, важно понимать, что во время компиляции и сборки секции этих файлов не имеют установленных адресов. При выполнении команды readelf -S file.o
вы заметите, что столбец "Address" будет заполнен нулями. Это значит, что компилятор не знает, где именно будет располагаться секция в конечном исполняемом файле, и, следовательно, адреса релокаций могут совпадать, так как они относительны к началу секции.
При слиянии (linkage) в процессе компоновки (linking) линковщик берет все секции из обоих файлов и устанавливает их адреса, начиная с некоторого базового адреса. Поскольку линковщик знает, как организовать секции, он может избежать конфликтов, переопределяя адреса в секциях A и B, если требуется. Таким образом, он гарантирует, что адреса релокации, указанные в обоих ELF-файлах, соотносятся корректно и не конфликтуют в окончательном скомпонованном файле.
2. Цель таблицы релокаций в ET_EXEC
Таблицы релокаций в файлах типа ET_EXEC нужны для корректной загрузки и выполнения программы, особенно когда речь идет о позиционно-независимом коде (PIC) и динамически загружаемых библиотеках. В случае использования PIC линковщик создаёт специальные записи, чтобы загрузчик (dynamic linker) мог корректно разрешать адреса в памяти при запуске. Если при компоновке используется флаг -no-pie
, таблица релокаций может не создаваться, за исключением случаев, когда используется опция --emit-relocs
.
Таким образом, таблица релокаций необходима для обеспечения динамического разрешения адресов во время выполнения программы, особенно в случаях совместимости с библиотеками и ПК.
3. Цель адденда в релокации типа Rela
Адденд (addend) в таблице релокаций типа Rela используется для хранения дополнительного значения, которое необходимо для корректного вычисления адреса. В отличие от REL, где адденд возможно хранится в другом месте, в RELA он фиксируется непосредственно в записи таблицы релокаций. Это позволяет менее зависимо хранить информацию и более эффективно её обрабатывать в процессе линковки:
- В случае REL адденд, как правило, извлекается из данных секции, что требует дополнительных операций.
- В случае RELA адденд уже присутствует в записи, что упрощает обработку на этапе линковки.
Оба формата (REL и RELA) имеют схожую функциональность, и выбор между ними может определяться предпочтениями разработчика или историческими аспектами его использования.
4. Пошаговое объяснение релокации
Релокация в ELF выполняется следующим образом:
- Разрешение символов: Линковщик сначала собирает всю необходимую информацию о символах, включая их адреса и значения, которые будут использоваться.
- Обработка таблицы релокаций: Линковщик проходит через таблицу релокаций и для каждой записи определяет, какой символ нужно использовать и какие адреса необходимо изменить.
- Вычисление адреса: На основе базового адреса, установленного для секции, и адденда, линковщик вычисляет конечный адрес, по которому должен находиться символ.
- Запись адреса: Линковщик записывает этот адрес в нужную часть сегмента или секции конечного файла.
Ресурсы для изучения
Для более глубокого понимания темы, я рекомендую следующие ресурсы:
- Книга «Linkers and Loaders»ом (обычно доступна в магазинной версии или библиотеках).
- Документация GNU Binutils, включая
readelf
иobjdump
. - Онлайн-курсы по системному программированию, посвященные работе с ELF и компоновщиками (например, на платформах Coursera или edX).
Эти материалы помогут вам более детально ознакомиться с процессами компоновки и релокации в формате ELF.