API для ldd (или objdump)?

Мне нужно программно проверить зависимости библиотеки данного исполняемого файла. Есть ли лучший способ, чем запускать команды ldd (или objdump) и анализировать их вывод? Есть ли API, дающий те же результаты, что и ldd?


person Saurabh Nanda    schedule 18.03.2020    source источник


Ответы (1)


Мне нужно программно проверить зависимости библиотеки данного исполняемого файла.

Я предполагаю, что вы используете систему ELF (возможно, Linux).

Зависимости динамических библиотек исполняемого файла или разделяемой библиотеки кодируются в виде таблицы на Elf{32_,64}_Dyn записях в PT_DYNAMIC сегменте библиотеки или исполняемого файла. ldd (косвенно, но это деталь реализации) интерпретирует эти записи, а затем использует различные детали конфигурации системы и / или LD_LIBRARY_PATH переменную среды для поиска необходимых библиотек.

Вы можете распечатать содержимое PT_DYNAMIC с помощью readelf -d a.out. Например:

$ readelf -d /bin/date

Dynamic section at offset 0x19df8 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x3000
 0x000000000000000d (FINI)               0x12780
 0x0000000000000019 (INIT_ARRAY)         0x1a250
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x1a258
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x308
 0x0000000000000005 (STRTAB)             0xb38
 0x0000000000000006 (SYMTAB)             0x358
 0x000000000000000a (STRSZ)              946 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x1b000
 0x0000000000000002 (PLTRELSZ)           1656 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x2118
 0x0000000000000007 (RELA)               0x1008
 0x0000000000000008 (RELASZ)             4368 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffb (FLAGS_1)            Flags: PIE
 0x000000006ffffffe (VERNEED)            0xf98
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0xeea
 0x000000006ffffff9 (RELACOUNT)          170
 0x0000000000000000 (NULL)               0x0

Это говорит о том, что единственная библиотека, необходимая для этого двоичного файла, - это libc.so.6 (запись NEEDED).

Если ваш реальный вопрос заключается в том, «какие еще библиотеки требуются для этого двоичного файла ELF», то это довольно легко получить: просто найдите DT_NEEDED записей в динамической таблице символов. Сделать это программно довольно просто:

  1. Найдите таблицу заголовков программ (заголовок файла ELF .e_phoff сообщает вам, где он начинается).
  2. Просмотрите их, чтобы найти тот, у которого есть PT_DYNAMIC .p_type.
  3. Этот сегмент содержит набор Elf{32,64}_Dyn записей фиксированного размера.
  4. Перебирайте их, ищите те, у которых есть .d_tag == DT_NEEDED.

Вуаля.

P.S. Есть небольшая сложность: строки, такие как libc.so.6, не являются частью PT_DYNAMIC. Но есть указатель на то, где они находятся в записи .d_tag == DT_STRTAB. См. Пример кода в этом ответе.

person Employed Russian    schedule 23.03.2020
comment
Привет, спасибо за ответ. Это сделало меня на шаг ближе к идеальному решению, но я еще не дошел до него. Я предполагаю, что вы предлагаете анализировать двоичный файл ELF, а не использовать буквально инструмент readelf, верно? Я делаю это в Haskell и нашел hackage.haskell .org / package / elf-0.30 / docs / Data-Elf.html, который выполняет работу по синтаксическому анализу двоичного файла ELF. - person Saurabh Nanda; 29.03.2020
comment
проанализированный двоичный файл ELF представлен этой записью Haskell - hackage.haskell.org/package/elf-0.30/docs/Data-Elf.html#t:Elf - и каждый раздел в двоичном файле представлен hackage.haskell.org/package/elf-0.30/docs/. Я могу найти сегмент с elfSegmentType==PT_DYNAMIC, но что дальше? Похоже, что данные для всех эльфийских сегментов представлены непрозрачным ByteString. Правильно ли я заключил, что библиотека не анализирует данные каждого сегмента (в зависимости от типа сегмента)? - person Saurabh Nanda; 29.03.2020
comment
@SaurabhNanda: Верно: я предлагаю анализировать данные напрямую. Также правильно: не похоже, что Data-Elf просматривает содержимое сегментов. Для этого вам придется написать код (но это довольно просто). - person Employed Russian; 29.03.2020
comment
Вы знаете простой документ, объясняющий формат раздела PT_DYNAMIC? Кроме того, как вы упомянули в своем ответе, этот раздел не будет содержать буквальных строк, а будет содержать ссылки на строки. Это похоже на hackage.haskell.org/ package / elf-0.30 / docs / уже разбирает все такие строки? - person Saurabh Nanda; 29.03.2020
comment
@SaurabhNanda Этот ответ сообщил вам формат PT_DYNAMIC: это набор записей ElfXX_Dyn фиксированного размера. Строки - это просто буквальные строки ASCII, упакованные одна за другой в один из PT_LOAD сегментов. Вам нужно будет найти этот сегмент нагрузки, сначала декодировав PT_DYNAMIC. - person Employed Russian; 29.03.2020
comment
Спасибо. Позвольте мне попробовать что-нибудь придумать. Ваш ответ касается моего первоначального вопроса. Мне нужно выяснить, как заставить это работать в Haskell. Спасибо за подробный ответ и за то, что вы ответили на мои дополнительные вопросы. - person Saurabh Nanda; 29.03.2020