#linux #linker #elf
#linux #компоновщик #elf
Вопрос:
Цитирование «Компоновщиков и загрузчиков» в части загрузчиков
«перемещение во время загрузки намного проще, чем перемещение во время соединения, потому что вся программа перемещается как единое целое. […] После считывания программы в память загрузчик просматривает элементы перемещения в объектном файле и исправляет ячейки памяти, на которые указывают элементы»
Возможно, я неправильно понял этот момент, и это только в некоторых архитектурах, но мой вопрос таков: где в формате ELF указано, какие элементы нуждаются в перемещении во время загрузки? как я могу запросить этот список?
Ответ №1:
Перемещения можно найти в специальных разделах перемещения в файле ELF. Вы можете использовать readelf --sections
команду, чтобы узнать, какие разделы есть в исполняемом файле или общей библиотеке, и какие разделы типа REL
содержат инструкции по перемещению. Содержимое этих разделов перемещения может быть отображено с помощью readelf --relocs
. Например:
$ readelf --relocs /bin/ls
Relocation section '.rela.dyn' at offset 0x16c8 contains 5 entries:
Offset Info Type Sym. Value Sym. Name Addend
00000061afd8 000c00000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ 0
00000061b540 006d00000005 R_X86_64_COPY 000000000061b540 optind 0
00000061b548 006e00000005 R_X86_64_COPY 000000000061b548 optarg 0
00000061b550 006a00000005 R_X86_64_COPY 000000000061b550 stderr 0
00000061b560 006600000005 R_X86_64_COPY 000000000061b560 stdout 0
Relocation section '.rela.plt' at offset 0x1740 contains 99 entries:
Offset Info Type Sym. Value Sym. Name Addend
00000061b000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 strcoll 0
00000061b008 000200000007 R_X86_64_JUMP_SLO 0000000000000000 mktime 0
...
.rela.dyn
Раздел содержит ссылки на ссылки в коде программы или символы данных, которые должны быть перемещены во время загрузки, в то время как .rela.plt
содержит в основном слоты перехода, которые используются для вызова функций в совместно используемых объектах. Обратите внимание, что обычно только общие объекты компилируются как код, не зависящий от позиции, в то время как обычные исполняемые файлы — нет. Это связано с тем, что код PIC немного медленнее, чем код без PIC.