Linux ldd что такое

Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.

Linux: ldd, starce, ltrace. Как работают утилиты. Трассировка вызовов.

libc — корневая библиотека языка CLinux мы ее видим по пути — /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 выводит список связанных, но не используемых разделяемых библиотек

stracesystem trace (трассировка системных вызовов)

ltracelibrary 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, ) = 0
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, ) = 0
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, ) = 0
mmap(NULL, 106075056, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f71d4d98000
close(3) = 0
open(«/etc/localtime», O_RDONLY|O_CLOEXEC) = 3
fstat(3, ) = 0
fstat(3, ) = 0
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, ) = 0
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

В Linux некоторые команды являются общими для всех, например ls, rm, mv, cp и т. Д. Я не думаю, что есть необходимость в подробностях их объяснения. Некоторые команды используются только разработчиками. Как программисты, мы, как программисты, должны понимать некоторые команды, а некоторые даже нужно использовать со знанием дела.

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

В этой статье мы познакомим вас с командой ldd, хотя она очень проста. Ой, я вдруг вспомнил, у меня есть подруга, ее зовут три символа, первая буква просто l, d, d, что отчасти интересно. В Linux ldd — это сокращение от list, dynamic, dependencies, что означает список зависимостей динамических библиотек. Конечно, вы также можете использовать ldd —help или man ldd, чтобы увидеть его использование. Ниже мы также рассмотрим:

Читайте также:  Где посмотреть настройки видеокарты windows 10

Выполните серию компиляций и используйте команду ldd, чтобы получить:

[[email protected] learn_ldd]$ ls
main.c test.c test.h
[[email protected] learn_ldd]$ gcc -c main.c test.c
[[email protected] learn_ldd]$ gcc main.o test.o
[[email protected] learn_ldd]$ ls
a.out main.c main.o test.c test.h test.o
[[email protected] learn_ldd]$ ./a.out
rainy days
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$ ldd *
a.out:
linux-gate.so.1 => (0x00ba1000)
libc.so.6 => /lib/libc.so.6 (0x0087e000)
/lib/ld-linux.so.2 (0x00858000)
main.c:
ldd: warning: you do not have execution permission for `./main.c’
not a dynamic executable
main.o:
ldd: warning: you do not have execution permission for `./main.o’
not a dynamic executable
test.c:
ldd: warning: you do not have execution permission for `./test.c’
not a dynamic executable
test.h:
ldd: warning: you do not have execution permission for `./test.h’
lddlibc4: cannot read header from `./test.h’
test.o:
ldd: warning: you do not have execution permission for `./test.o’
not a dynamic executable
[[email protected] learn_ldd]$
Вы можете видеть, что a.out зависит от библиотеки libc.so.6, а путь к этой библиотеке — /lib/libc.so.6

Давайте продолжим рассмотрение использования библиотек статических ссылок:

[[email protected] learn_ldd]$ ls
main.c test.c test.h
[[email protected] learn_ldd]$ gcc -c test.c
[[email protected] learn_ldd]$ ar rcs libtest.a test.o
[[email protected] learn_ldd]$ gcc main.c -L. -ltest
[[email protected] learn_ldd]$ ls
a.out libtest.a main.c test.c test.h test.o
[[email protected] learn_ldd]$ ./a.out
rainy days
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$ ldd *
a.out:
linux-gate.so.1 => (0x00e7c000)
libc.so.6 => /lib/libc.so.6 (0x0087e000)
/lib/ld-linux.so.2 (0x00858000)
libtest.a:
ldd: warning: you do not have execution permission for `./libtest.a’
not a dynamic executable
main.c:
ldd: warning: you do not have execution permission for `./main.c’
not a dynamic executable
test.c:
ldd: warning: you do not have execution permission for `./test.c’
not a dynamic executable
test.h:
ldd: warning: you do not have execution permission for `./test.h’
lddlibc4: cannot read header from `./test.h’
test.o:
ldd: warning: you do not have execution permission for `./test.o’
not a dynamic executable
[[email protected] learn_ldd]$
На этот раз с использованием статической библиотеки результат все тот же, сказать нечего.

Давайте продолжим рассмотрение ситуации при использовании библиотек динамической компоновки:

[[email protected] learn_ldd]$ ls
main.c test.c test.h
[[email protected] learn_ldd]$ gcc -c test.c
[[email protected] learn_ldd]$ gcc -shared -fPIC -o libtest.so test.o
[[email protected] learn_ldd]$ gcc main.c -L. -ltest
[[email protected] learn_ldd]$ ls
a.out libtest.so main.c test.c test.h test.o
[[email protected] learn_ldd]$ ./a.out
./a.out: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$ ldd *
a.out:
linux-gate.so.1 => (0x00f3d000)
libtest.so => not found
libc.so.6 => /lib/libc.so.6 (0x0087e000)
/lib/ld-linux.so.2 (0x00858000)
libtest.so:
linux-gate.so.1 => (0x0031d000)
libc.so.6 => /lib/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00858000)
main.c:
ldd: warning: you do not have execution permission for `./main.c’
not a dynamic executable
test.c:
ldd: warning: you do not have execution permission for `./test.c’
not a dynamic executable
test.h:
ldd: warning: you do not have execution permission for `./test.h’
lddlibc4: cannot read header from `./test.h’
test.o:
ldd: warning: you do not have execution permission for `./test.o’
not a dynamic executable
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$ su root
Password:
[[email protected] learn_ldd]# cp libtest.so /usr/lib/
[[email protected] learn_ldd]# ./a.out
rainy days
[[email protected] learn_ldd]# exit
exit
[[email protected] learn_ldd]$ ./a.out
rainy days
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$
[[email protected] learn_ldd]$ ldd a.out
linux-gate.so.1 => (0x00510000)
libtest.so => /usr/libtest.so (0x00fe3000)
libc.so.6 => /lib/libc.so.6 (0x0087e000)
/lib/ld-linux.so.2 (0x00858000)

Читайте также:  Try linux without installing

Прежде всего, мы видим, что a.out зависит от библиотеки libtest.so, но результата не обнаружено. Почему? Поскольку в / usr / lib нет libtest.so, позже я скопировал libtest.so (требуются права root), и все было в порядке. Кроме того, мы также должны увидеть, что зависимые библиотеки libtest.so также можно найти с помощью команды ldd.

Конечно, если вы не хотите писать свою собственную программу, но хотите попробовать команду ldd, вы можете сделать это напрямую следующим образом:

[[email protected] learn_ldd]$ ldd /bin/ls
linux-gate.so.1 => (0x0052b000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00b52000)
librt.so.1 => /lib/librt.so.1 (0x00a5c000)
libcap.so.2 => /lib/libcap.so.2 (0x0489c000)
libacl.so.1 => /lib/libacl.so.1 (0x048c9000)
libc.so.6 => /lib/libc.so.6 (0x0087e000)
libdl.so.2 => /lib/libdl.so.2 (0x00a0c000)
/lib/ld-linux.so.2 (0x00858000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00a13000)
libattr.so.1 => /lib/libattr.so.1 (0x04d99000)
[[email protected] learn_ldd]$ ldd /bin/mv
linux-gate.so.1 => (0x00944000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00b52000)
librt.so.1 => /lib/librt.so.1 (0x00a5c000)
libacl.so.1 => /lib/libacl.so.1 (0x048c9000)
libattr.so.1 => /lib/libattr.so.1 (0x04d99000)
libc.so.6 => /lib/libc.so.6 (0x00110000)
libdl.so.2 => /lib/libdl.so.2 (0x00a0c000)
/lib/ld-linux.so.2 (0x00858000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00a13000)
[[email protected] learn_ldd]$

При реальной разработке и отладке Linux необходимо часто проверять зависимости динамических библиотек, ldd все еще используется довольно часто, особенно когда происходит сбой. Хорошо, здесь кратко представлена ​​команда ldd. Несмотря на простоту, она очень практична, поэтому вы должны ее знать.

Источник

Оцените статью