Linux посмотреть зависимости бинарника

Обновлено: 04.07.2024

Я хотел бы знать, какие библиотеки используются исполняемыми файлами в моей системе. В частности, я хотел бы ранжировать, какие библиотеки используются больше всего, вместе с исполняемыми файлами, которые их используют. Как я могу это сделать?

ОТВЕТЫ

Ответ 1

  • Используйте ldd для отображения разделяемых библиотек для каждого исполняемого файла.
  • Очистка вывода
  • Сортировка, подсчет, сортировка по счету

Чтобы найти ответ для всех исполняемых файлов в каталоге "/bin":

Измените "/bin" выше на "/", чтобы найти все каталоги.

Выход (только для каталога /bin ) будет выглядеть примерно так:

Изменить - Удалено "grep -P"

Ответ 2

У меня не было ldd на моей инструментальной привязке ARM, поэтому я использовал objdump:

$(CROSS_COMPILE) objdump -p

Ответ 3

чтобы узнать, какие библиотеки используют двоичные файлы, используйте ldd

Вам нужно написать небольшую оболочку script, чтобы получить разбивку по всей системе.

Ответ 4

В Linux я использую:

Это работает лучше, чем ldd , когда исполняемый файл использует нестандартный загрузчик

Ответ 5

Проверка зависимостей общей библиотеки исполняемого файла

Чтобы узнать, от каких библиотек зависит конкретный исполняемый файл, вы можете использовать команду ldd. Эта команда вызывает динамический компоновщик для поиска зависимостей библиотек от исполняемого файла.

$ldd/path/to/program

Обратите внимание, что НЕ рекомендуется запускать ldd с любым ненадежным сторонним исполняемым файлом, поскольку некоторые версии ldd могут напрямую вызывать исполняемый файл для идентификации его зависимостей в библиотеке, что может представлять угрозу безопасности.

Вместо этого более безопасный способ отображения зависимостей библиотеки неизвестного двоичного файла приложения заключается в использовании следующей команды.

$objdump -p/path/to/program | grep NEEDED

Ответ 6

readelf -d рекурсия

Но имейте в виду, что динамические библиотеки могут зависеть от других динамических библиотек, которые вам придется использовать.

Выберите один и повторите:

/proc/<pid>/maps для запуска процессов

Это полезно, чтобы найти все библиотеки, которые в данный момент используются исполняемыми файлами. Например.:

показывает все загруженные в настоящий момент динамические зависимости init (PID 1 ):

Этот метод также показывает библиотеки, открытые с помощью dlopen , протестированные с помощью этой минимальной настройки, взломанные с помощью sleep(1000) в Ubuntu 18.04.

Ответ 7

В OS X по умолчанию нет ldd , objdump или lsof . В качестве альтернативы попробуйте otool -L :

В этом примере использование which openssl заполняет полный путь для данной исполняемой и текущей пользовательской среды.

Ответ 8

В системе UNIX предположим, что двоичное (исполняемое) имя является тестом. Затем мы используем следующую команду для отображения библиотек, используемых в тесте,

Ответ 9

С помощью ldd вы можете получить библиотеки, которые используют инструменты. Чтобы ранжировать использование библиотек для набора инструментов, вы можете использовать что-то вроде следующей команды.

(Здесь sed удаляет все строки, которые не начинаются с вкладки, и фильтры исключают только фактические библиотеки. С помощью sort | uniq -c вы получаете каждую библиотеку с указанием количества раз, когда оно произошло.)

Возможно, вы захотите добавить sort -g в конце, чтобы получить библиотеки в порядке их использования.

Обратите внимание, что вы, вероятно, получите две строки, отличные от библиотеки, с приведенной выше командой. Один из статических исполняемых файлов ( "не динамический исполняемый файл" ) и один без какой-либо библиотеки. Последнее является результатом linux-gate.so.1 , который не является библиотекой в ​​вашей файловой системе, а один "предоставляется" ядром.

Ответ 10

на убунту печать пакетов, связанных с исполняемым файлом

Ответ 11

Еще один вариант можно просто прочитать файл, расположенный в

Например, если идентификатор процесса - 2601, тогда команда -

И вывод похож на

Ответ 12

Я нашел этот пост очень полезным, поскольку мне нужно было исследовать зависимости от сторонней поставляемой библиотеки (32 или 64-битные пути выполнения).

Я собрал Q & D, рекурсивный bash script на основе предложения 'readelf -d' в дистрибутиве RHEL 6.

Он очень простой и будет проверять каждую зависимость каждый раз, даже если он, возможно, был протестирован раньше (то есть очень подробный). Выход также очень прост.


Есть ли способ определения какие packages и каких версий понадобятся при развертке приложения?

Я могу получить список всех so посредством ldd, но там не указано в какие packages входят эти библиотеки.

У вас есть какой-то бинарник, а не нормальный пакет, который вы собираетесь «разворачивать»? Зависимости по уровням версий есть только на уровне работы с пакетами, при работе с бинарниками можно ориентироваться только на версию ABI. Лучше свяжитесь с тем, кто компилировал бинарник, чтобы уточнить с какими версиями библиотек он линковался. Мне надо свой пакет собрать, соответственно мне нужно прописать зависимости с версиями для пакета. спасибо, но мне нужен список зависимостей с версиями, а не способ создания package.

Во-первых, почему не указали это сразу? Во-вторых, рекомендуем и желателен именно традиционный подход к сборке пакетов. В официальных репах дебиана и убунты нет ни одного пакета собранных cpack´ом. В-третьих, apt-file´ом находите все пакеты, в которых используются файлы из отчёта ldd и пишите их в зависимости, но это будет во-о-от такой рогатый костыль.

Мне всё-таки до сих пор не понятно. Невозможно спросить разработчика на предмет зависимостей и адаптировать этот список под реалии дистрибутива?

Почему не указал? Очень просто, я не спрашивал как мне собрать пакет, я спрашивал как найти зависимости, остальное меня не интересует, на данный момент. В контексте моего вопроса присутствие cpack совершенно не важно.
Разработчика спросить можно, это я. Но я хочу четкий список зависимостей из бинарника, а не из того, что я знаю, что я использовал.
Другими словами: есть способ достичь того, чего я хочу или нет? Без советов как мне создать пакет, просто ответьте на мой вопрос, пожалуйста.

Тогда никак, архитектура elf этого не предоставляет. В голову приходят мысли о специальной среде, позволяющей собирать и тестировать бинарник с разными версиями библиотек (тот же buildbot), но это довольно объёмная задача.

Когда-то давно у меня была самописная игрушка, использовавшая libSDL, libSDL_mixer, libSDL_image, physfs, lua. Тогда я собирал пакет прописывая их как зависимости, естественно отбрасывая libpng, zlib, libc и пр., так как от них и так зависят используемые мной библиотеки. Если же хотите привязаться к версиям, то можете просто указать >= текущая_версия_пакета.

Спасибо! Я вот что нашел, но приведенный там скрипт не работает, ибо я нашел только игру pacman :) А дополненный скрипт не существует, может наведет кого-нибудь на идею…

PKGS=`(for lib in $LIBS; do
apt-file -Fl search $lib
done) | sort | uniq`

(for pkg in $PKGS; do
echo $pkg `apt-cache show $pkg | grep Version | awk ''`
done)

]% test.sh /usr/bin/mc
e2fslibs 1.41.12-2
libc6 2.11.2-13
libcomerr2 1.41.12-2
libglib2.0-0 2.28.2-1
libgpm2 1.20.4-3.3
libpcre3 8.12-3
libslang2 2.2.2-4

Теперь смотрим, как же оно на самом деле:
[

]% apt-cache show mc | grep Depends
Depends: e2fslibs (>= 1.41.0), libc6 (>= 2.3), libcomerr2 (>= 1.01), libglib2.0-0 (>= 2.24.0), libgpm2 (>= 1.20.4), libslang2 (>= 2.0.7-1)
Или более детально:
[

]% apt-cache showpkg mc | grep -A1 Dependencies
Dependencies:
3:4.7.0.9-1 - e2fslibs (2 1.41.0) libc6 (2 2.3) libcomerr2 (2 1.01) libglib2.0-0 (2 2.24.0) libgpm2 (2 1.20.4) libslang2 (2 2.0.7-1) perl (0 (null)) zip (0 (null)) unzip (0 (null)) bzip2 (0 (null)) links (16 (null)) w3m (16 (null)) lynx (0 (null)) arj (0 (null)) file (0 (null)) xpdf-reader (16 (null)) pdf-viewer (0 (null)) dbview (0 (null)) odt2txt (0 (null)) gv (0 (null)) catdvi (0 (null)) djvulibre-bin (0 (null)) imagemagick (0 (null)) python (0 (null)) python-boto (0 (null)) python-tz (0 (null)) mime-support (0 (null))
Или более наглядно:
[

]% apt-cache depends mc
mc
Зависит: e2fslibs
Зависит: libc6
Зависит: libcomerr2
Зависит: libglib2.0-0
Зависит: libgpm2
Зависит: libslang2
Предлагает: perl
Предлагает: zip
Предлагает: unzip
Предлагает: bzip2
|Предлагает: links
|Предлагает: w3m
Предлагает: lynx
Предлагает: arj
Предлагает: file
|Предлагает: xpdf-reader
Предлагает: <pdf-viewer>
acroread
epdfview
evince
evince-gtk
gv
okular
viewpdf.app
xpdf
zathura
Предлагает: dbview
Предлагает: odt2txt
Предлагает: gv
Предлагает: catdvi
Предлагает: djvulibre-bin
Предлагает: imagemagick
graphicsmagick-imagemagick-compat
Предлагает: python
Предлагает: python-boto
Предлагает: python-tz
Рекомендует: mime-support

А теперь обратите внимание на libpcre3, это зависимость libglib2.0-0. Чем больше у вас будет высокоуровневых библиотек, тем больше будет лишних зависимостей. Повторяю опять, зависимости надо или заполнять руками или ориентироваться на dh_shlibdeps, который тоже в свою очередь обычно нужно подстраивать под действительность. Причём я не зря вам привёл ещё и другие поля, для большинства пакетов это тоже существенные дополнения, от которых зависит его функциональность. А если ещё вспомнить про конфликты, замены, виртуальные пакеты…

В Linux исполняемые файлы можно условно разделить на две группы – те, которые содержат в себе весь код, необходимые для работы, и те, которым необходимы разделяемые библиотеки. Первые называют статически собранными бинарными файлами, вторые называют динамически собранными исполняемыми файлами.

Статически собранные программы характеризуются тем, что могут корректно функционировать в любых условиях, и не зависят от наличия или отсутствия разделяемых библиотек, что может оказаться полезным в ситуациях, когда возникают конфликты версий разделяемых библиотек, или когда системные библиотеки повреждены или недоступны (например во время восстановления операционной системы после серьезного сбоя). К недостаткам таких исполняемых файлов следует отнести то, что они имеют значительный размер и для обновления программы необходимо полностью заменить ее исполняемый файл – например, если несколько статически собранных программ, которые работают с архивами ZIP, содержат ошибку, то для исправления ошибки необходимо заменить все эти программы, что может быть затруднено (например, будет трудно точно установить, какие именно программы содержат ошибочный код и нуждаются в обновлении). Кроме того, статически собранные программы не умеют совместно использовать совпадающие участки кода, что ведет к излишнему расходу системных ресурсов.

Динамически собранные исполняемые файлы для корректной работы требуют наличия файлов разделяемых библиотек, и соответственно при их отсутствии/повреждении не могут корректно функционировать, но зато для обновления программы и исправления ошибки часто оказывается достаточным просто заменить соответствующую разделяемую библиотеку, после чего ошибка исчезает во всех программах, которые эту библиотеку используют динамически. Динамически связанные программы также значительно меньше по объему, чем статически связанные, и код разделяемых библиотек может использоваться одновременно многими программами – что позволяет экономить системные ресурсы.

Подавляющее большинство программ в современных дистрибутивах Linux являются динамически собранными. Определить тип исполняемого файла (статический ли он либо с динамическим связыванием) можно, например, с помощью команды ldd:

Но здесь нас подстерегает несколько НО:

1) Существует способ загрузки библиотек в обход ldd, функцией dlopen(). Такие библиотеки в выводе ldd не отображены.

То есть, мало того, что не все библиотеки (в идеале) мы сможем увидеть, так ещё и запускаем на исполнение файл! А если это руткит? Что же делать? Выход есть, правда не совсем удобный.

Выход второй (для пунктов 1 и 2): использовать команду strace. Правда вывод не такой удобный будет, как в случае с ldd.

Так же можно эту информацию получить и таким образом:

Для более детальной вычинки бинарника можно использовать утилиту objdump и strace.

error while loading shared libraries: xxxx.so.0
cannot open shared object file no such file or directory

Это значит, что нет подходящих библиотек. Но что делать, если они есть, а система их не находит? На помощь приходит утилита ldconfig, которая управляет динамическими библиотеками.

Подробнее можно узнать в справочном руководстве.

Так же можно использовать переменную окружения LD_LIBRARY_PATH.

Примечание.

UPD: Запись перенесена из старого блога, опубликована в 2015 году.

Предисловие

Системному администратору зачастую очень важно понимать как устроена система, как настроить/отладить те ли иные вещи и как искать ошибки в работе. Если устройству и настройке можно достаточно легко научиться из различных руководств и справочных страниц, где написано что система сделана вот так вот, а настраивается она вот этими кнопочками и командами, то вот с отладкой и поиском проблем зачастую возникают проблемы. Для многих, к сожалению, система представляет собой черный ящик, с входом и выходом и магией внутри. Я покажу как немного пролить свет на эту темноту внутри ящика.

Он будет развернут у меня на виртуальной машине в VirtualBox, с использованием снапшотов. Это нужно для того, чтобы смело экспериментировать и не бояться поломать свою систему.


Выясним что же это за дистрибутив


Этой информации достаточно для того чтобы начать поиск документации и описания различных знаний, специфичных для этой системы ( например управление через GUI, хорошие практики настройки и эксплуатации и пр).

Однако, узнав что это по сути, один из стандартных Linux дистрибутивов мы можем смело сказать, что в составе уже есть минимально-необходимый комплект инструментов для отладки ( универсальный для всех Linux систем, за исключением каких-нибудь очень специфичных). Продолжим знакомство теперь уже с ними:

Трассировщики и доп. утилиты

Для того чтобы наблюдать за программой которая обращается к ядру ос, ее библиотекам, системным вызовам, ресурсам и пр нам понадобятся трассировщики.

Покажу Вам парочку стандартных инструмнетов:



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



Обычно мы вводим команду в командном интерпретаторе и получаем ответ, не задумываясь- а это была встроенная команда или сторонняя программа, запуск которой был вызван вводом команды. А ведь то, что в одном дистрибутиве является встроенной командой оболочки, в другом может повлечь вызов программы. А место вызова программы может быть переопределено (в том числе и злоумышленником) и вместо простого вызова sudo, Вы запустите стороннюю утилиту, которая сохранит и отправит Ваш пароль кому-нибудь еще. which позволяет узнать где лежит та или иная программа.


В зависимости от ее вывода, мы можем понять- что чем является. То, что лежит в:

либо является встроенной командой.

Теперь, раз мы уже так много знаем и умеем, давайте разберемся в самих файлах и программах чуть глубже- спросим у утилиты file про нее же саму и посмотрим, что она нам скажет?


нам скажут что это:

Отладчик необходим, если мы не можем понять, что происходит внутри программы а исходных текстов у нас нет. Или есть, но мы подозреваем, что компилятор произвел некорректную оптимизацию, внеся ошибки в результирующий бинарный код, хотя в тексте программы ошибок не было.

Продолжим исследование программы file


После этого встает вопрос- а как же библиотека загружает другие библиотеки если ее тоже кто-то должен загрузить и загрузить ее библиотеки?

Вспомним, что библиотеки это тоже файлы-программы. Между ними нет никакой разницы кроме одного маленького исключения. Посмотрим его ( тут я переключусь на свою локальную консоль, ибо так будет удобней):





Либо более простая ситуация- произошло что-то плохое с диском, что повлияло на блок, в котором располагалось часть кода библиотеки. В следствии чего она не смогла быть корректно запущена. Посмотрим на наш командный интерпретатор



Пример использования 1. окружение


Теперь немного поработаем ей- попробуем определить типы различных файлов


Как это работает- они либо смотрит, чем является файл на файловой системе, либо заглядывает внутрь и пытается выяснить тип файла сигнатурным способом.


Мы уже видели, что она зависит от библиотеки libmagic. Логично было бы убедиться в том, что она использует этот сигнатурный способ на практике, а не основываясь на моих словах. Сделать мы это можем путем предположения, что именно эта библиотека и отвечает за анализ сигнатур ( ведь остальные являются стандартными системными библиотеками, а эта как то выделяется). Аналогичным способом мы могли бы выяснить что Libz отвечает за работу с архивами. Как нам это сделать?

Еще в самом начале мы выяснили, что у нас система основана на ubuntu, а значит, поковырявшись в справочной информации мы узнаем что это ветка развития Debian а значит использует его менеджер пакетов dpkg ( как раз та самая дистрибутив-специфичная информация).

Так давайте спросим- из какого пакета была инсталлирована та или иная библиотека.

Он скажет что она была инсталирована из пакета libmagic1 для платформы intel 386. Спросим теперь что это за зверь?


Все становится более-менее понятно. И видим что программа file не может жить без библиотеки, а значит пакет с программой зависит от пакета с библиотекой. Вот вам живая иллюстрация зависимостей програмного обеспечения.

Что мы видим? что в этом пакете не только библиотека но еще и пара файлов ( и их контрольные суммы):

Conffiles:
/etc/magic 272913026300e7ae9b5e2d51f138e674
/etc/magic.mime 272913026300e7ae9b5e2d51f138e674

Хотя если это не очевидно, то мы можем запросить список файлов, входящих в пакет.



Тут мы можем подробно почитать о том что это и зачем нужно. Из чего он состоит и как утилита file его использует. Но нам же интересно и на сам файл с сигнатурами посмотреть?

file -L /usr/share/misc/magic.mgc


Сама утилита файл подтверждает полученную ранее информацию- да, это файл, содержащий те самые магические числа.

А мы можем его посмотреть? Попробуем, воспользовавшись утилитой less для просмотра текстовых файлов


К сожалению, она нам говорит что не уверена что он текстовый и даже если мы прикажем его просмотреть- не сможет это сделать. А может утилита cat нам поможет? Нет, увы- она замусорит нам консоль.


То есть очевидно что там все же не совсем текстовое содержимое, а скорее сигнатуры и их описание. Отлично- вот как много мы уже выяснили, зная лишь про одну утилиту file и исследуя ее окружение.

Теперь, давайте попробуем посмотреть то, что она делает и как она это делает.

Пример использования 2. Трассировка

Итак, посмотрим за поведением утилиты file во время ее работы, для этого используем упомянутые выше утилиты strace и ltrace и построим трассы вызовов.


Вв конечном итоге это превращается в попытку открыть библиотеки от которых зависит программа и считать их содержимое.


Далее, программа открывает свой конфигурационный файл и файл, который как мы предполагали, содержит сигнатуры


А дальше она пытается открыть и обработать тот файл, который мы попросили проанализировать:

Разбирает список аргументов



читает его заголовок


находит в заголовке какие-то только ей понятные искомые структуры данных


Далее, считав что нужно, она его анализирует (это мы к сожалению не увидим, т.к. обработка происходит внутри программы без использования системных вызовов) и в конце концов выдает результат:




Итого, путем всех этих препарирований, мы четко для себя выяснили схему работы программы:

  • загрузиться в память и загрузить все библиотеки
  • получить список аргументов и разобрать его
  • найти анализируемый файл
  • открыть и прочитать свои magic файлы
  • обратиться к своей библиотеке
  • проанализировать информацию
  • напечатать результат

А мы все увидели это с помощью трассировщиков.

Работа со справочной информацией

Но откуда нам знать что делают те или иные функции? Очень просто- почитать встроенную справку. Например мы видели функцию putc, почитаем справку про нее:


Но если мы попробуем найти хоть какую-то информацию о наших магических функциях, нас ждет разочарование:


Почему так произошло? Да очень просто- установив пакет с библиотекой, мы установили минимально необходимый для запуска программы набор компонентов, оставив в стороне набор компонентов разработчика, такой как заголовочные файлы и страницы справочного руководства. Их так же можно доустановить из пакетов так же, как мы ставим все прочее программное обеспечение.


Среди списка рекомендуемых пакетов в описании увы нет ничего похожего ( например одноименные библиотеки с суфиксами doc или dev), поэтому проведем поиск по имени пакета среди доступных:


Отлично, мы нашли нужный пакет и убедились в том что это он, прочтя описание. Установим и поковыряемся в нем. Установка производится командой

sudo aptitude install libmagic-dev


Отлично, у нас появилась документация разработчика- посмотрим раздел 3 справочного руководства по библиотеке libmagic и мы найдем там описание нужной функции:


На этом первая часть работы с инструментарием закончена, продолжение будет в следующей статье.

П.С. Данная статья ( и последующие аналогичные) подготовлена на основе конспекта лекций Кетова Дмитрия Владимировича. От себя я добавил редактуру, несколько измененный стиль изложения, свои правки и комментарии.

Читайте также: