Як дізнатись динамічні навантаження виконуваних файлів бібліотек при запуску?


Відповіді:


61

Це можна зробити за допомогою lddкоманди:

NAME
       ldd - print shared library dependencies

SYNOPSIS
       ldd [OPTION]...  FILE...

DESCRIPTION
       ldd  prints  the  shared  libraries  required by each program or shared
       library specified on the command line.
....

Приклад:

$ ldd /bin/ls
    linux-vdso.so.1 =>  (0x00007fff87ffe000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007ff0510c1000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff050eb9000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007ff050cb0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff0508f0000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff0506ec000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff0512f7000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff0504ce000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007ff0502c9000)

1
Будь-яке уявлення про те, що було б еквівалентом цього macOS? Ні, lldу Дарвіні це не з'являється, і я не можу знайти його через домашню мову.
mz2

7
На macOS:otool -L <path-to-binary>
Річард Віней

пам’ятайте, що це може виконати двійковий код. Тож якщо двійковий файл не є довірливим, можливо, краще не використовувати ldd. Див. Сторінку чоловіка .
Пол Руні

46

readelf -d $executable | grep 'NEEDED'

Може використовуватися, якщо ви не можете запустити виконуваний файл, наприклад, якщо він був складений хрестоподібно або якщо ви не довіряєте йому:

У звичайному випадку ldd викликає стандартний динамічний лінкер (див. Ld.so (8)) зі змінною середовища LD_TRACE_LOADED_OBJECTS, встановленою на 1, що змушує лінкер відображати залежність бібліотеки. Однак майте на увазі, що за деяких обставин деякі версії ldd можуть намагатися отримати інформацію про залежність, безпосередньо виконуючи програму. Таким чином, ви ніколи не повинні використовувати ldd на ненадійному виконуваному файлі, оскільки це може призвести до виконання довільного коду.

Приклад:

readelf -d /bin/ls | grep 'NEEDED'

Вибірка зразка:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Зауважте, що бібліотеки можуть залежати від інших бібліотек, тому тепер вам потрібно знайти залежності.

Наївний підхід, який часто працює:

$ locate libselinux.so.1
/lib/i386-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libselinux.so.1
/mnt/debootstrap/lib/x86_64-linux-gnu/libselinux.so.1

але більш точний метод - зрозуміти lddшлях пошуку / кеш. Я думаю, що ldconfigце шлях.

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

readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'

Вибірка зразка:

0x0000000000000001 (NEEDED)             Shared library: [libpcre.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

І так далі.

Дивитися також:

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

Про це згадував Базіле , це корисно для пошуку всіх бібліотек, якими зараз користуються запущені версії файлів. Наприклад:

sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u

показує всі завантажені в даний час динамічні залежності init(PID 1):

/lib/x86_64-linux-gnu/ld-2.23.so
/lib/x86_64-linux-gnu/libapparmor.so.1.4.0
/lib/x86_64-linux-gnu/libaudit.so.1.0.0
/lib/x86_64-linux-gnu/libblkid.so.1.1.0
/lib/x86_64-linux-gnu/libc-2.23.so
/lib/x86_64-linux-gnu/libcap.so.2.24
/lib/x86_64-linux-gnu/libdl-2.23.so
/lib/x86_64-linux-gnu/libkmod.so.2.3.0
/lib/x86_64-linux-gnu/libmount.so.1.1.0
/lib/x86_64-linux-gnu/libpam.so.0.83.1
/lib/x86_64-linux-gnu/libpcre.so.3.13.2
/lib/x86_64-linux-gnu/libpthread-2.23.so
/lib/x86_64-linux-gnu/librt-2.23.so
/lib/x86_64-linux-gnu/libseccomp.so.2.2.3
/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libuuid.so.1.3.0

Цей метод також показує бібліотеки, відкриті dlopen, протестовані з цією мінімальною установкою, підключеною до sleep(1000)Ubuntu 18.04.

Дивіться також: Як побачити завантажені в даний час спільні об'єкти в Linux? | Супер Користувач


1
Приємна частина методу readelf полягає в тому, що він працює і на крос-бінарних файлах (наприклад: armhf на amd64) також
Ghostrider

13

ldd та lsof показують бібліотеки, завантажені безпосередньо або в даний момент . Вони не враховують бібліотеки, завантажені через dlopen(або відкидаютьсяdlclose ). Ви можете отримати кращу картину цього, використовуючи strace, наприклад,

strace -e trace=open myprogram

(оскільки в dlopenкінцевому рахунку дзвінки open- хоча, звичайно, ви можете мати систему, що використовує різні назви для 64-розрядних відкриттів ...).

Приклад:

strace -e trace=open date

показує мені це:

open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
open("/etc/localtime", O_RDONLY)        = 3
Wed Apr 12 04:56:32 EDT 2017

з якого можна було б назбирати імена ".so", щоб просто побачити спільні об'єкти.


3
Поліпшення:strace -e trace=open,openat myprogram
Cyker

Хороший метод. /proc/<pid>/mapsтакож показано dlopenlibs btw: unix.stackexchange.com/questions/120015/… ltrace -S вихід ще крутіший, оскільки він показує як системні дзвінки, так і виклики бібліотеки на зразок dlopen: unix.stackexchange.com/questions/226524/…
Ciro Santilli 新疆 改造 中心 法轮功 六四事件

7

lsof також може показати вам, які бібліотеки використовуються для одного конкретного процесу.

тобто

$ pidof nginx
6920 6919

$ lsof -p 6919|grep mem
nginx   6919 root  mem    REG               0,64    65960     43 /lib64/libnss_files-2.12.so
nginx   6919 root  mem    REG               0,64    19536     36 /lib64/libdl-2.12.so
nginx   6919 root  mem    REG               0,64    10312   1875 /lib64/libfreebl3.so
nginx   6919 root  mem    REG               0,64  1923352     38 /lib64/libc-2.12.so
nginx   6919 root  mem    REG               0,64    88600   1034 /lib64/libz.so.1.2.3
nginx   6919 root  mem    REG               0,64  1967392   1927 /usr/lib64/libcrypto.so.1.0.1e
nginx   6919 root  mem    REG               0,64   183080   1898 /lib64/libpcre.so.0.0.1
nginx   6919 root  mem    REG               0,64    40400   1217 /lib64/libcrypt-2.12.so
nginx   6919 root  mem    REG               0,64   142688     77 /lib64/libpthread-2.12.so
nginx   6919 root  mem    REG               0,64   154664     31 /lib64/ld-2.12.so

2

Для процесу pid 1234 ви також можете прочитати /proc/1234/maps(текстовий) псевдофайл (читати proc (5) ...) або використовувати pmap (1)

Це дає віртуальний адресний простір цього процесу, отже файли (включаючи спільні бібліотеки, навіть dlopen (3) -ed), які відображаються в пам'яті

(звичайно, використовуйте ps auxабо pgrep (1) для пошуку процесів, які виконують певну програму)


1

Для масового запиту:

  1. створити невеликий скрипт ( useslib) і ввести в PATH (або уточнити повний шлях в команді нижче)

    #! /bin/bash
    ldd $1 | grep -q $2
    exit $?
    
  2. Використовуйте його в findкоманді, наприклад:

    find /usr/bin/ -executable -type f -exec useslib {} libgtk-x11-2.0 \; -print
    

(libgtk-x11-2.0, схоже, libt gtk2)


0

Можливе використання pmap.

Наприклад, запустіть процес: $ watch date

Отримайте під: $ ps -ef | grep watch

Показати карту пам'яті: $ pmap <pid>

Показати з повним контуром: $ pmap <pid> -p

$ pmap 72770
72770:   watch date
00005613a32c9000     20K r-x-- watch
00005613a34cd000      4K r---- watch
00005613a34ce000      4K rw--- watch
00005613a4f6a000    264K rw---   [ anon ]
00007f2f3a7d5000 204616K r---- locale-archive
00007f2f46fa7000   1748K r-x-- libc-2.27.so
00007f2f4715c000   2048K ----- libc-2.27.so
00007f2f4735c000     16K r---- libc-2.27.so
00007f2f47360000      8K rw--- libc-2.27.so
00007f2f47362000     16K rw---   [ anon ]
00007f2f47366000     12K r-x-- libdl-2.27.so
00007f2f47369000   2044K ----- libdl-2.27.so
00007f2f47568000      4K r---- libdl-2.27.so
00007f2f47569000      4K rw--- libdl-2.27.so
00007f2f4756a000    160K r-x-- libtinfo.so.6.1
00007f2f47592000   2048K ----- libtinfo.so.6.1
00007f2f47792000     16K r---- libtinfo.so.6.1
00007f2f47796000      4K rw--- libtinfo.so.6.1
00007f2f47797000    232K r-x-- libncursesw.so.6.1
00007f2f477d1000   2048K ----- libncursesw.so.6.1
00007f2f479d1000      4K r---- libncursesw.so.6.1
00007f2f479d2000      4K rw--- libncursesw.so.6.1
00007f2f479d3000    148K r-x-- ld-2.27.so
00007f2f47bdb000     20K rw---   [ anon ]
00007f2f47bf1000     28K r--s- gconv-modules.cache
00007f2f47bf8000      4K r---- ld-2.27.so
00007f2f47bf9000      4K rw--- ld-2.27.so
00007f2f47bfa000      4K rw---   [ anon ]
00007ffd39404000    136K rw---   [ stack ]
00007ffd3959b000     12K r----   [ anon ]
00007ffd3959e000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           215692K
$ pmap 72770 -p
72770:   watch date
00005613a32c9000     20K r-x-- /usr/bin/watch
00005613a34cd000      4K r---- /usr/bin/watch
00005613a34ce000      4K rw--- /usr/bin/watch
00005613a4f6a000    264K rw---   [ anon ]
00007f2f3a7d5000 204616K r---- /usr/lib/locale/locale-archive
00007f2f46fa7000   1748K r-x-- /usr/lib64/libc-2.27.so
00007f2f4715c000   2048K ----- /usr/lib64/libc-2.27.so
00007f2f4735c000     16K r---- /usr/lib64/libc-2.27.so
00007f2f47360000      8K rw--- /usr/lib64/libc-2.27.so
00007f2f47362000     16K rw---   [ anon ]
00007f2f47366000     12K r-x-- /usr/lib64/libdl-2.27.so
00007f2f47369000   2044K ----- /usr/lib64/libdl-2.27.so
00007f2f47568000      4K r---- /usr/lib64/libdl-2.27.so
00007f2f47569000      4K rw--- /usr/lib64/libdl-2.27.so
00007f2f4756a000    160K r-x-- /usr/lib64/libtinfo.so.6.1
00007f2f47592000   2048K ----- /usr/lib64/libtinfo.so.6.1
00007f2f47792000     16K r---- /usr/lib64/libtinfo.so.6.1
00007f2f47796000      4K rw--- /usr/lib64/libtinfo.so.6.1
00007f2f47797000    232K r-x-- /usr/lib64/libncursesw.so.6.1
00007f2f477d1000   2048K ----- /usr/lib64/libncursesw.so.6.1
00007f2f479d1000      4K r---- /usr/lib64/libncursesw.so.6.1
00007f2f479d2000      4K rw--- /usr/lib64/libncursesw.so.6.1
00007f2f479d3000    148K r-x-- /usr/lib64/ld-2.27.so
00007f2f47bdb000     20K rw---   [ anon ]
00007f2f47bf1000     28K r--s- /usr/lib64/gconv/gconv-modules.cache
00007f2f47bf8000      4K r---- /usr/lib64/ld-2.27.so
00007f2f47bf9000      4K rw--- /usr/lib64/ld-2.27.so
00007f2f47bfa000      4K rw---   [ anon ]
00007ffd39404000    136K rw---   [ stack ]
00007ffd3959b000     12K r----   [ anon ]
00007ffd3959e000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           215692K
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.