В настоящее время я работаю над проектом, включающим реконструкцию общей библиотеки (на виртуальной машине x64, Linux), специально ориентированной на musl-libc (версия: 1.1.15).
После реконструкции библиотеки musl-libc новая библиотека не запускается (обратите внимание, что сама musl-libc также является двоичным исполняемым файлом).
В частности, когда я запускаю оригинальную musl-libc с помощью:
./libc.so
Я ожидаю следующий результат:
musl libc (x86_64)
Version 1.1.15
Dynamic Program Loader
Usage: ./libc.so [options] [--] pathname [args]
Однако запуск моей реконструированной версии приводит к:
bash: ./libc.so.rewritten: cannot execute binary file: Exec format error
Моя цель — диагностировать проблему, вызывающую сбой выполнения. Я проверил readelf -aвыходные данные моей реконструированной библиотеки, и все выглядит просто «отлично». Поэтому для выявления проблемы необходим дальнейший анализ процесса загрузки.
На данный момент я понимаю, что двоичный исполняемый файл обычно содержит раздел .interp, в котором указывается путь к динамическому загрузчику. Однако в musl-libc нет раздела .interp. Вот вывод readelf -lW ./libc.so для справки:
Elf file type is DYN (Shared object file)
Entry point 0x5d9c4
There are 7 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000188 0x000188 R 0x8
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x08eda4 0x08eda4 R E 0x1000
LOAD 0x08f980 0x0000000000090980 0x0000000000090980 0x000a70 0x003954 RW 0x1000
DYNAMIC 0x08fe18 0x0000000000090e18 0x0000000000090e18 0x000130 0x000130 RW 0x8
GNU_EH_FRAME 0x08ed80 0x000000000008ed80 0x000000000008ed80 0x000024 0x000024 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
GNU_RELRO 0x08f980 0x0000000000090980 0x0000000000090980 0x000680 0x000680 RW 0x10
...
Любые советы и предложения будут очень признательны. Заранее спасибо!
Обновлено: Ниже приведен вывод readelf -h для libc.so.rewrite.
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x191c1
Start of program headers: 64 (bytes into file)
Start of section headers: 867576 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 79
Size of section headers: 64 (bytes)
Number of section headers: 92
Section header string table index: 91
@IanAbbott, я добавил вывод readelf -h
Заголовки выглядят аналогично (кроме размеров и смещений) файлу /usr/lib/x86_64-linux-musl/libc.so, установленному пакетом musl в моей системе Debian, за исключением того, что у меня есть только 9 заголовков программ и 20 заголовков разделов, и этот файл работает нормально в моей системе. Оба readelf -h и readelf -lW сообщают о 9 заголовках программы. Интересно, что ваш readelf -h сообщает о 79 заголовках программ, а ваш readelf -lW сообщает о 7 заголовках программ (может быть, опечатка?).
@IanAbbott Привет, Ян. readelf -lw взят из libc.so (исходная версия musl-libc), а недавно добавленный результат readelf -h взят из libc.so.rewrite (моя реконструированная версия musl-libc). Я погрузился в этот сегмент кода в исходный файл libc.so. В результате libc.so.rewrite имеет 79 заголовков программ (и это цель реконструкции разделяемой библиотеки).
Благодаря совету @IanAbbott я пытаюсь диагностировать эту проблему с помощью функции load_elf_binary(), которая в конечном итоге вызывается execve для загрузки двоичных файлов ELF.





Перед загрузкой двоичного файла elf ядро выполняет некоторые проверки работоспособности (ниже приведен исходный код, скопированный из функции load_elf_phdrs() в fs/binfmt_elf.c):
/* Sanity check the number of program headers... */
/* ...and their total size. */
size = sizeof(struct elf_phdr) * elf_ex->e_phnum;
if (size == 0 || size > 65536 || size > ELF_MIN_ALIGN)
goto out;
Здесь предполагается, что размер заголовков программы меньше ELF_MIN_ALIGN. Поэтому он отказывается выполнять мою восстановленную библиотеку, поскольку ее заголовок программы превышает эту длину.
Для его выполнения не требуется динамический загрузчик. Если вы запустите
strace ./libc.so.rewritten, вы, вероятно, увидите ошибкуENOEXEC, возникающую непосредственно из системного вызоваexecve. Можете ли вы показать результатreadelf -h ./libc.so.rewritten?