- Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.
- Ldd linux что это
- Примеры использования
- Вывод списка разделяемых библиотек, используемых приложением
- Вывод списка разделяемых библиотек, используемых разделяемой библиотекой
- Вывод подробного списка разделяемых библиотек, используемых приложением
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 — функции вывода
Источник
Ldd linux что это
Команда 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.
Источник