- Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.
- 8 Примеров команд LDD в Linux
- Общие библиотеки
- Синтаксис и параметры
- 1) Отобразить зависимости команды
- 2) Отобразить зависимости команды с деталями
- 3) Отображение неиспользуемых прямых зависимостей команды
- 4) Работа только с динамическими исполняемыми файлами
- 5) ldd со стандартной исполняемой командой
- 6) Установите, что данный исполняемый демон поддерживает TCP Wrapper
- 7) ldd с отсутствующей зависимостью
- What is linux ldd
- Примеры использования
- Вывод списка разделяемых библиотек, используемых приложением
- Вывод списка разделяемых библиотек, используемых разделяемой библиотекой
- Вывод подробного списка разделяемых библиотек, используемых приложением
Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.
Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.
libc — корневая библиотека языка C (В Linux мы ее видим по пути — /lib64/libc.so.6)
6 — номер версии библиотеки
По сути является ссылкой на библиотеку libc-2.17.so:
# ls -l /lib64/libc.so.6
lrwxrwxrwx. 1 root root 12 Jan 30 04:27 /lib64/libc.so.6 -> libc-2.17.so
Что будем использовать для примера?
ldd — выводит список разделяемых библиотек, используемых указанной утилитой или разделяемой библиотекой
Разделяемые библиотеки содержат реализации функций, необходимых для работы приложений, разделяемых библиотек
Разделяемые библиотеки имеют расширение — «.so» ( аналоги динамических библиотек «.dll» Windows )
Опция -v выводит информацию о версиях используемых разделяемых библиотек
Опция -u выводит список связанных, но не используемых разделяемых библиотек
strace — system trace (трассировка системных вызовов)
ltrace — library trace (трассировка библиотечных вызовов)
Посмотрим, что использует утилита date:
# which date | xargs ldd
linux-vdso.so.1 => (0x00007ffd3d3d8000)
libc.so.6 => /lib64/libc.so.6 (0x00007f931f97d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f931fd4b000)
Посмотрим, как отрабатывают системные вызовы при вызове утилиты date:
# which date | xargs strace
execve(«/bin/date», [«/bin/date»], [/* 22 vars */]) = 0
brk(NULL) = 0x20ab000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f71db8b0000
access(«/etc/ld.so.preload», R_OK) = -1 ENOENT (No such file or directory)
open(«/etc/ld.so.cache», O_RDONLY|O_CLOEXEC) = 3
fstat(3,
mmap(NULL, 57295, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f71db8a2000
close(3) = 0
open(«/lib64/libc.so.6», O_RDONLY|O_CLOEXEC) = 3
read(3, «\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0». 832) = 832
fstat(3,
mmap(NULL, 3985888, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f71db2c2000
mprotect(0x7f71db485000, 2097152, PROT_NONE) = 0
mmap(0x7f71db685000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f71db685000
mmap(0x7f71db68b000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f71db68b000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f71db8a1000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f71db89f000
arch_prctl(ARCH_SET_FS, 0x7f71db89f740) = 0
mprotect(0x7f71db685000, 16384, PROT_READ) = 0
mprotect(0x60d000, 4096, PROT_READ) = 0
mprotect(0x7f71db8b1000, 4096, PROT_READ) = 0
munmap(0x7f71db8a2000, 57295) = 0
brk(NULL) = 0x20ab000
brk(0x20cc000) = 0x20cc000
brk(NULL) = 0x20cc000
open(«/usr/lib/locale/locale-archive», O_RDONLY|O_CLOEXEC) = 3
fstat(3,
mmap(NULL, 106075056, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f71d4d98000
close(3) = 0
open(«/etc/localtime», O_RDONLY|O_CLOEXEC) = 3
fstat(3,
fstat(3,
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f71db8af000
read(3, «TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\0». 4096) = 3519
lseek(3, -2252, SEEK_CUR) = 1267
read(3, «TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\5\0\0\0\5\0\0\0\0». 4096) = 2252
close(3) = 0
munmap(0x7f71db8af000, 4096) = 0
fstat(1,
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f71db8af000
write(1, «Thu Mar 12 17:22:20 EDT 2020\n», 29Thu Mar 12 17:22:20 EDT 2020
) = 29
close(1) = 0
munmap(0x7f71db8af000, 4096) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
Кратко из вывода strace (набора вызовов к ядру операционной системы) мы видим:
execve — системный вызов, указывает, что для работы команды date необходимо загрузить утилиту по пути /bin/date
open — системные вызовы, которые загружают указанные библиотеки и файлы, в которых есть зависимость (вывод ldd)
read — системные вызовы, осуществляющме чтение оных
Так-же в выводе присутствует ряд действий
Пример: «open(«/etc/localtime», O_RDONLY|O_CLOEXEC) = 3″ — считывается файл с зоной
write — собственно вывод результата работы утилиты (вывод на экран)
Пример трассировки определенных вызовов:
# which date | xargs strace -fe open,read,write,close
open(«/etc/ld.so.cache», O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
open(«/lib64/libc.so.6», O_RDONLY|O_CLOEXEC) = 3
read(3, «\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20&\2\0\0\0\0\0». 832) = 832
close(3) = 0
open(«/usr/lib/locale/locale-archive», O_RDONLY|O_CLOEXEC) = 3
close(3) = 0
open(«/etc/localtime», O_RDONLY|O_CLOEXEC) = 3
read(3, «TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\4\0\0\0\0». 4096) = 3519
read(3, «TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\5\0\0\0\5\0\0\0\0». 4096) = 2252
close(3) = 0
write(1, «Thu Mar 12 17:59:02 EDT 2020\n», 29Thu Mar 12 17:59:02 EDT 2020
) = 29
close(1) = 0
close(2) = 0
+++ exited with 0 +++
Посмотрим, как отрабатывают библиотечные вызовы при вызове утилиты date:
# which date | xargs ltrace
__libc_start_main(0x401ab0, 1, 0x7ffc7e59ae08, 0x4096e0
strrchr(«/bin/date», ‘/’) = «/date»
setlocale(LC_ALL, «») = «en_US.UTF-8»
bindtextdomain(«coreutils», «/usr/share/locale») = «/usr/share/locale»
textdomain(«coreutils») = «coreutils»
__cxa_atexit(0x402c40, 0, 0, 0x736c6974756572) = 0
getopt_long(1, 0x7ffc7e59ae08, «d:f:I::r:Rs:u», 0x60d2a0, nil) = -1
nl_langinfo(0x2006c, 1, 0, 0) = 0x7f890e9a2025
clock_gettime(0, 0x7ffc7e59ac40, 0xc94440, 0) = 0
localtime(0x7ffc7e59abc0) = 0x7f8915103d20
strftime(» Thu», 1024, » %a», 0x7f8915103d20) = 4
fwrite(«Thu», 3, 1, 0x7f89150ff400) = 1
fputc(‘ ‘, 0x7f89150ff400) = 32
strftime(» Mar», 1024, » %b», 0x7f8915103d20) = 4
fwrite(«Mar», 3, 1, 0x7f89150ff400) = 1
fputc(‘ ‘, 0x7f89150ff400) = 32
fwrite(«12», 2, 1, 0x7f89150ff400) = 1
fputc(‘ ‘, 0x7f89150ff400) = 32
fwrite(«17», 2, 1, 0x7f89150ff400) = 1
fputc(‘:’, 0x7f89150ff400) = 58
fwrite(«23», 2, 1, 0x7f89150ff400) = 1
fputc(‘:’, 0x7f89150ff400) = 58
fputc(‘0’, 0x7f89150ff400) = 48
fwrite(«3», 1, 1, 0x7f89150ff400) = 1
fputc(‘ ‘, 0x7f89150ff400) = 32
strlen(«EDT») = 3
fwrite(«EDT», 3, 1, 0x7f89150ff400) = 1
fputc(‘ ‘, 0x7f89150ff400) = 32
fwrite(«2020», 4, 1, 0x7f89150ff400) = 1
__overflow(0x7f89150ff400, 10, 4, 0x30323032Thu Mar 12 17:23:03 EDT 2020
) = 10
exit(0
__fpending(0x7f89150ff400, 0, 64, 0x7f89150ffeb0) = 0
fileno(0x7f89150ff400) = 1
__freading(0x7f89150ff400, 0, 64, 0x7f89150ffeb0) = 0
__freading(0x7f89150ff400, 0, 2052, 0x7f89150ffeb0) = 0
fflush(0x7f89150ff400) = 0
fclose(0x7f89150ff400) = 0
__fpending(0x7f89150ff1c0, 0, 3328, 0xfbad000c) = 0
fileno(0x7f89150ff1c0) = 2
__freading(0x7f89150ff1c0, 0, 3328, 0xfbad000c) = 0
__freading(0x7f89150ff1c0, 0, 4, 0xfbad000c) = 0
fflush(0x7f89150ff1c0) = 0
fclose(0x7f89150ff1c0) = 0
+++ exited (status 0) +++
Из вывода ltrace мы видим:
clock_gettime — по сути функция, получающая время системы
strftime — форматирование в нужном формате
fwrite и fputc — функции вывода
Источник
8 Примеров команд LDD в Linux
ldd – это утилита командной строки Linux, которая используется в том случае, если пользователь хочет знать зависимости от общей библиотеки исполняемого файла или даже библиотеки разделяемой библиотеки.
Библиотека представляет собой набор ресурсов, таких как подпрограммы / функции, классы, значения или спецификации типов.
Существует два типа библиотек:
Статические библиотеки: статические библиотеки для полных программ, которые не зависят от запуска внешних библиотек. Особенностью статически связанных программ является то, что они работают без установки каких-либо предварительных условий. Статическая библиотека заканчивается расширением * .a, и эти библиотеки включены (отдельная копия) в программы, для которых требуются ее функции.
Динамические библиотеки: динамические библиотеки для небольших программ по размеру. Эти библиотеки заканчиваются расширением .so. Еще одна особенность использования динамической компоновки при запуске многих программ. Она может использовать одну копию библиотеки, а не занимать память многими копиями одного и того же кода , Таким образом, последние программы используют динамическое связывание. В этой статье мы рассмотрим команды ldd, которые используются для управления разделяемыми библиотеками.
Общие библиотеки
Когда мы создаем программу, нам нужно много фрагментов кода, которые кто-то написал для выполнения обычных или специализированных функций в наших целях.
Эти фрагменты кода хранятся в разделяемых библиотеках.
Чтобы использовать их, мы связываем их с нашим кодом либо при создании программы, либо при запуске программы.
Синтаксис и параметры
Команда ldd выводит зависимости общих объектов. Синтаксис команды:
Мы можем использовать команды ldd с опциями
- -v: вывести всю информацию.
- -d: перемещение данных процесса.
- -r: данные процесса и перемещение функций.
- -u: вывод неиспользуемых прямых зависимостей.
1) Отобразить зависимости команды
Мы будем отображать зависимости команды cp.
2) Отобразить зависимости команды с деталями
Мы будем отображать зависимости команды cp с более подробной информацией, используя опцию -v.
3) Отображение неиспользуемых прямых зависимостей команды
Мы можем отобразить неиспользуемые прямые зависимости команды cp с использованием опции -u.
4) Работа только с динамическими исполняемыми файлами
Мы выведем ldd только для динамических исполняемых файлов с использованием опции -r.
На выводе было отображено сообщение о том, что предоставленный файл не является динамическим исполняемым файлом.
5) ldd со стандартной исполняемой командой
Когда мы пытаемся выполнить ldd со стандартной командой, например ls, нам нужен полный путь к динамическому исполняемому файлу.
Мы видим, что ldd утверждает, что он не может найти ls.
Но с абсолютным путем ldd работал нормально.
6) Установите, что данный исполняемый демон поддерживает TCP Wrapper
Чтобы определить, поддерживает ли данный исполняемый демона TCP Wrapper или нет, выполните следующую команду.
Результат показывает, что демон OpenSSH (sshd) поддерживает TCP Wrapper.
7) ldd с отсутствующей зависимостью
Мы можем использовать команду ldd, когда исполняемый файл выходит из строя из-за отсутствующей зависимости.
Как только мы обнаружили недостающую зависимость, мы можем установить ее или обновить кеш командой ldconfig.
Мы будем выполнять перемещение и сообщать о любых недостающих объектах (только ELF), набрав команду ниже.
Мы будем выполнять перемещение для объектов и функций данных и сообщать о любых недостающих объектах или функциях (только для ELF), набрав команду ниже.
Источник
What is linux ldd
Команда ldd предназначена для вызова одноименной утилиты, осуществляющей вывод списка разделяемых библиотек, используемых исполняемыми файлами или разделяемыми библиотеками. Разделяемые библиотеки обычно содержат реализации функций, которые необходимы для корректной работы приложений или других разделяемых библиотек. Разделяемые библиотеки (*.so) являются полным аналогом динамических библиотек (*.dll) из Windows.
Базовый синтаксис команды выглядит следующим образом:
$ ldd [параметры] [путь-к-разделяемой-библиотеке]
Утилита поддерживает параметр -v, позволяющий выводить дополнительную информацию о версиях используемых разделяемых библиотек, параметр -u, позволяющий выводить список связанных, но не используемых разделяемых библиотек, а также параметры -d и -r, позволяющие осуществлять релокации объектов данных и функций.
Рассматриваемая утилита может понадобиться в процессе разработки программного обеспечения, а также создания пакетов для его распространения.
Стоит упомянуть и о том, что система кэширует информацию о доступных разделяемых библиотеках и хранит ее в файле с именем /etc/ld.so.cache (файл не предназначен для редактирования с помощью обычного текстового редактора). Существует и файл конфигурации /etc/ld.so.conf, в котором содержится список путей к директориям, в которых размещены разделяемые библиотеки. Разделяемая библиотека с именем ld-linux-*.so выполняет функции динамического линковщика, то есть, осуществляет поиск необходимых для работы приложения разделяемых библиотек в кэше и загружает их. Помимо этого существует системная утилита ldconfig, предназначенная для обновления кэша разделяемых библиотек.
Также существует вспомогательная виртуальная разделяемая библиотека linux-vdso.so (или linux-gate.so на некоторых архитектурах), которая отображается ядром Linux в адресное пространство всех пользовательских процессов и используется библиотекой языка C libc для повышения производительности при работе с некоторыми системными вызовами. На нее не стоит обращать особого внимания.
Примеры использования
Вывод списка разделяемых библиотек, используемых приложением
Для вывода списка разделяемых библиотек, используемых приложением, следует передать утилите путь к интересующему приложению.
$ ldd /bin/nano
linux-vdso.so.1 (0x00007ffc5e1d3000)
libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007fed3b9e8000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fed3b9b8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fed3b7c7000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fed3b7c1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fed3ba8f000)
Как видно, для работы приложения nano требуется ряд разделяемых библиотек, причем первой библиотекой является вспомогательная библиотека ядра Linux, а последней — библиотека динамического линковщика.
Вывод списка разделяемых библиотек, используемых разделяемой библиотекой
Для вывода списка разделяемых библиотек, используемых другой разделяемой библиотекой, следует передать утилите путь к интересующей разделяемой библиотеке.
$ ldd /lib/x86_64-linux-gnu/libc-2.30.so
/lib64/ld-linux-x86-64.so.2 (0x00007f8d28fad000)
linux-vdso.so.1 (0x00007ffe62b78000)
Библиотека libc использует лишь вспомогательные разделяемые библиотеки.
$ ldd /lib/x86_64-linux-gnu/libbz2.so.1
linux-vdso.so.1 (0x00007ffc757cb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3bd62f4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3bd6516000)
Библиотека libbz2 использует библиотеку libc.
Вывод подробного списка разделяемых библиотек, используемых приложением
Для вывода подробного списка разделяемых библиотек, используемых приложением, следует использовать параметр -v.
$ ldd -v /bin/nano
linux-vdso.so.1 (0x00007fff4cfcf000)
libncursesw.so.6 => /lib/x86_64-linux-gnu/libncursesw.so.6 (0x00007f43c1744000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f43c1714000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f43c1523000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f43c151d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f43c17eb000)
Version information:
/bin/nano:
libtinfo.so.6 (NCURSES6_TINFO_5.4.20040208) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.0.19991023) => /lib/x86_64-linux-gnu/libtinfo.so.6
libc.so.6 (GLIBC_2.27) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.6) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
libncursesw.so.6 (NCURSESW6_5.7.20081102) => /lib/x86_64-linux-gnu/libncursesw.so.6
libncursesw.so.6 (NCURSESW6_5.1.20000708) => /lib/x86_64-linux-gnu/libncursesw.so.6
/lib/x86_64-linux-gnu/libncursesw.so.6:
libdl.so.2 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libdl.so.2
libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.7) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.9.20150530) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.5.20051010) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.1.20000708) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.2.20001021) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.6.20061217) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.7.20081102) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.8.20110226) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.4.20040208) => /lib/x86_64-linux-gnu/libtinfo.so.6
libtinfo.so.6 (NCURSES6_TINFO_5.0.19991023) => /lib/x86_64-linux-gnu/libtinfo.so.6
/lib/x86_64-linux-gnu/libtinfo.so.6:
libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.16) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6:
ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libdl.so.2:
ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
libc.so.6 (GLIBC_PRIVATE) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
Информация о версиях библиотек приведена в разделе Version information.
Источник