Устранение неполадок при выполнении общей библиотеки musl-libc

описание проблемы

В настоящее время я работаю над проектом, включающим реконструкцию общей библиотеки (на виртуальной машине 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
...

Вопросы

  • Проблема с динамическим загрузчиком. Может ли проблема быть связана с динамическим загрузчиком? Если да, то какой динамический загрузчик используется для загрузки musl-libc? Использует ли он динамический загрузчик glibc или динамический загрузчик musl-libc (т. е. сам musl-libc)?
  • Механизм загрузки ОС: Альтернативно, загружает ли ОС musl-libc напрямую через execve? Если это так, поможет ли добавление журналов в определенную функцию ядра (отвечающую за загрузку двоичных файлов ELF) в диагностике проблемы?

Любые советы и предложения будут очень признательны. Заранее спасибо!

Обновлено: Ниже приведен вывод 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

Для его выполнения не требуется динамический загрузчик. Если вы запустите strace ./libc.so.rewritten, вы, вероятно, увидите ошибку ENOEXEC, возникающую непосредственно из системного вызова execve. Можете ли вы показать результат readelf -h ./libc.so.rewritten?

Ian Abbott 30.05.2024 16:47

@IanAbbott, я добавил вывод readelf -h

Chibi Gwen 31.05.2024 10:39

Заголовки выглядят аналогично (кроме размеров и смещений) файлу /usr/lib/x86_64-linux-musl/libc.so, установленному пакетом musl в моей системе Debian, за исключением того, что у меня есть только 9 заголовков программ и 20 заголовков разделов, и этот файл работает нормально в моей системе. Оба readelf -h и readelf -lW сообщают о 9 заголовках программы. Интересно, что ваш readelf -h сообщает о 79 заголовках программ, а ваш readelf -lW сообщает о 7 заголовках программ (может быть, опечатка?).

Ian Abbott 31.05.2024 12:10

@IanAbbott Привет, Ян. readelf -lw взят из libc.so (исходная версия musl-libc), а недавно добавленный результат readelf -h взят из libc.so.rewrite (моя реконструированная версия musl-libc). Я погрузился в этот сегмент кода в исходный файл libc.so. В результате libc.so.rewrite имеет 79 заголовков программ (и это цель реконструкции разделяемой библиотеки).

Chibi Gwen 31.05.2024 12:29

Благодаря совету @IanAbbott я пытаюсь диагностировать эту проблему с помощью функции load_elf_binary(), которая в конечном итоге вызывается execve для загрузки двоичных файлов ELF.

Chibi Gwen 31.05.2024 12:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Перед загрузкой двоичного файла 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. Поэтому он отказывается выполнять мою восстановленную библиотеку, поскольку ее заголовок программы превышает эту длину.

Другие вопросы по теме