ldd – это утилита командной строки Linux, которая используется в том случае, если пользователь хочет знать зависимости от общей библиотеки исполняемого файла или даже библиотеки разделяемой библиотеки.
Библиотека представляет собой набор ресурсов, таких как подпрограммы / функции, классы, значения или спецификации типов.
Существует два типа библиотек:
Статические библиотеки: статические библиотеки для полных программ, которые не зависят от запуска внешних библиотек. Особенностью статически связанных программ является то, что они работают без установки каких-либо предварительных условий. Статическая библиотека заканчивается расширением * .a, и эти библиотеки включены (отдельная копия) в программы, для которых требуются ее функции.
Динамические библиотеки: динамические библиотеки для небольших программ по размеру. Эти библиотеки заканчиваются расширением .so. Еще одна особенность использования динамической компоновки при запуске многих программ. Она может использовать одну копию библиотеки, а не занимать память многими копиями одного и того же кода , Таким образом, последние программы используют динамическое связывание. В этой статье мы рассмотрим команды ldd, которые используются для управления разделяемыми библиотеками.
Общие библиотеки
Когда мы создаем программу, нам нужно много фрагментов кода, которые кто-то написал для выполнения обычных или специализированных функций в наших целях.
Эти фрагменты кода хранятся в разделяемых библиотеках.
Чтобы использовать их, мы связываем их с нашим кодом либо при создании программы, либо при запуске программы.
Синтаксис и параметры
Команда ldd выводит зависимости общих объектов. Синтаксис команды:
ldd [OPTION]... FILE...
Мы можем использовать команды ldd с опциями
- -v: вывести всю информацию.
- -d: перемещение данных процесса.
- -r: данные процесса и перемещение функций.
- -u: вывод неиспользуемых прямых зависимостей.
1) Отобразить зависимости команды
Мы будем отображать зависимости команды cp.
$ ldd /bin/cp
Output: linux-vdso.so.1 => (0x00007fffaf3ff000) libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003a06a00000) librt.so.1 => /lib64/librt.so.1 (0x0000003a06200000) libacl.so.1 => /lib64/libacl.so.1 (0x0000003a13000000) libattr.so.1 => /lib64/libattr.so.1 (0x0000003a0ea00000) libc.so.6 => /lib64/libc.so.6 (0x0000003a05200000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003a05a00000) /lib64/ld-linux-x86-64.so.2 (0x0000003a04a00000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a05600000)
2) Отобразить зависимости команды с деталями
Мы будем отображать зависимости команды cp с более подробной информацией, используя опцию -v.
$ ldd -v /bin/cp
Output: linux-vdso.so.1 => (0x00007fff473ff000) libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003a06a00000) librt.so.1 => /lib64/librt.so.1 (0x0000003a06200000) libacl.so.1 => /lib64/libacl.so.1 (0x0000003a13000000) libattr.so.1 => /lib64/libattr.so.1 (0x0000003a0ea00000) libc.so.6 => /lib64/libc.so.6 (0x0000003a05200000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003a05a00000) /lib64/ld-linux-x86-64.so.2 (0x0000003a04a00000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a05600000) Version information: /bin/cp: librt.so.1 (GLIBC_2.2.5) => /lib64/librt.so.1 libattr.so.1 (ATTR_1.1) => /lib64/libattr.so.1 libacl.so.1 (ACL_1.2) => /lib64/libacl.so.1 libacl.so.1 (ACL_1.0) => /lib64/libacl.so.1 libc.so.6 (GLIBC_2.6) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 /lib64/libselinux.so.1: libdl.so.2 (GLIBC_2.2.5) => /lib64/libdl.so.2 ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2 libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.8) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 /lib64/librt.so.1: libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0 libpthread.so.0 (GLIBC_PRIVATE) => /lib64/libpthread.so.0 libc.so.6 (GLIBC_2.3.2) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 libc.so.6 (GLIBC_PRIVATE) => /lib64/libc.so.6 /lib64/libacl.so.1: libattr.so.1 (ATTR_1.0) => /lib64/libattr.so.1 libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 /lib64/libattr.so.1: libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 /lib64/libc.so.6: ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2 ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2 /lib64/libdl.so.2: ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2 libc.so.6 (GLIBC_PRIVATE) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6 /lib64/libpthread.so.0: ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2 ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2 ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2 libc.so.6 (GLIBC_2.3.2) => /lib64/libc.so.6 libc.so.6 (GLIBC_PRIVATE) => /lib64/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
3) Отображение неиспользуемых прямых зависимостей команды
Мы можем отобразить неиспользуемые прямые зависимости команды cp с использованием опции -u.
$ ldd -u /bin/cp
Output: Unused direct dependencies: /lib64/libselinux.so.1 /lib64/librt.so.1 /lib64/libacl.so.1 /lib64/libattr.so.1
4) Работа только с динамическими исполняемыми файлами
Мы выведем ldd только для динамических исполняемых файлов с использованием опции -r.
$ ldd -r /smart/pycharm-community-2017.3.3/bin/pycharm.sh
Output: not a dynamic executable
На выводе было отображено сообщение о том, что предоставленный файл не является динамическим исполняемым файлом.
5) ldd со стандартной исполняемой командой
Когда мы пытаемся выполнить ldd со стандартной командой, например ls, нам нужен полный путь к динамическому исполняемому файлу.
$ ldd ls
Output: ldd: ./ls: No such file or directory
Мы видим, что ldd утверждает, что он не может найти ls.
$ ldd /bin/ls
Output: linux-vdso.so.1 => (0x00007fff5cbea000) libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003a06a00000) librt.so.1 => /lib64/librt.so.1 (0x0000003a06200000) libcap.so.2 => /lib64/libcap.so.2 (0x0000003a07600000) libacl.so.1 => /lib64/libacl.so.1 (0x0000003a13000000) libc.so.6 => /lib64/libc.so.6 (0x0000003a05200000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003a05a00000) /lib64/ld-linux-x86-64.so.2 (0x0000003a04a00000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003a05600000) libattr.so.1 => /lib64/libattr.so.1 (0x0000003a0ea00000)
Но с абсолютным путем ldd работал нормально.
6) Установите, что данный исполняемый демон поддерживает TCP Wrapper
Чтобы определить, поддерживает ли данный исполняемый демона TCP Wrapper или нет, выполните следующую команду.
$ sudo ldd /usr/sbin/sshd | grep libwrap
Output: libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1cc2ac6000)
Результат показывает, что демон OpenSSH (sshd) поддерживает TCP Wrapper.
7) ldd с отсутствующей зависимостью
Мы можем использовать команду ldd, когда исполняемый файл выходит из строя из-за отсутствующей зависимости.
Как только мы обнаружили недостающую зависимость, мы можем установить ее или обновить кеш командой ldconfig.
$ sudo ldd /bin/mv
libacl.so.1 => /lib/libacl.so.1 (0×40016000) libc.so.6 => /lib/libc.so.6 (0x4001c000) libattr.so.1 => /lib/libattr.so.1 (0×40141000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
Мы будем выполнять перемещение и сообщать о любых недостающих объектах (только ELF), набрав команду ниже.
$ sudo ldd -d path/to/executable_file
Мы будем выполнять перемещение для объектов и функций данных и сообщать о любых недостающих объектах или функциях (только для ELF), набрав команду ниже.
$ sudo ldd -r path/to/executable_file