Comment connaître le chargement des bibliothèques dynamiques exécutables lors de l'exécution?

64

Je veux connaître la liste des bibliothèques dynamiques qu'un binaire charge lorsqu'il est exécuté (avec leurs chemins d'accès complets). J'utilise CentOS 6.0. Comment faire ça?

Ciro Santilli 改造 中心 六四 事件
la source

Réponses:

61

Vous pouvez le faire avec la lddcommande:

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.
....

Exemple:

$ 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)
cuonglm
la source
1
Une idée de ce que serait un équivalent macOS de cela? Non lldsur darwin, semble-t-il, et je ne peux pas le trouver via homebrew.
mz2
7
Sur macOS:otool -L <path-to-binary>
Richard Viney
sachez que cela peut exécuter le binaire. Donc, si le fichier binaire n'est pas approuvé, il peut être préférable de ne pas l'utiliser ldd. Voir la page de manuel .
Paul Rooney
47

readelf -d $executable | grep 'NEEDED'

Peut être utilisé si vous ne pouvez pas exécuter l'exécutable, par exemple s'il a été compilé de manière croisée, ou si vous ne lui faites pas confiance:

Dans le cas habituel, ldd appelle l'éditeur de liens dynamique standard (voir ld.so (8)) avec la variable d'environnement LD_TRACE_LOADED_OBJECTS définie sur 1, ce qui oblige l'éditeur de liens à afficher les dépendances de la bibliothèque. Sachez toutefois que, dans certaines circonstances, certaines versions de ldd peuvent tenter d'obtenir les informations de dépendance en exécutant directement le programme. Ainsi, vous ne devriez jamais utiliser ldd sur un exécutable non approuvé, car cela pourrait entraîner l'exécution de code arbitraire.

Exemple:

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

Exemple de sortie:

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

Notez que les bibliothèques peuvent dépendre d'autres bibliothèques, vous devez donc maintenant rechercher les dépendances.

Une approche naïve qui fonctionne souvent est la suivante:

$ 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

mais la méthode la plus précise consiste à comprendre le lddchemin / cache de recherche. Je pense que ldconfigc'est la voie à suivre.

Choisissez-en un et répétez:

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

Exemple de sortie:

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]

Etc.

Voir également:

/proc/<pid>/maps pour les processus en cours

Mentionné par Basile , il est utile de rechercher toutes les bibliothèques actuellement utilisées par les exécutables en cours d'exécution. Par exemple:

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

affiche toutes les dépendances dynamiques de init(PID 1) actuellement chargées :

/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

Cette méthode montre également les bibliothèques ouvertes avec dlopen, testées avec cette configuration minimale piratée avec un sleep(1000)sur Ubuntu 18.04.

Voir aussi: Comment voir les objets partagés actuellement chargés dans Linux? | Super utilisateur

Ciro Santilli 改造 中心 六四 事件
la source
1
Une bonne partie de la méthode readelf est que cela fonctionne aussi sur les binaires croisés (ex: armhf sur amd64)
Ghostrider
13

ldd et lsof montrent les bibliothèques chargées directement ou à un moment donné . Ils ne tiennent pas compte des bibliothèques chargées via dlopen(ou rejetés pardlclose ). Vous pouvez obtenir une meilleure image de ceci en utilisant strace, par exemple,

strace -e trace=open myprogram

(puisque dlopenfinalement des appels open- bien que vous puissiez bien sûr avoir un système utilisant des noms différents pour les ouvertures 64 bits ...).

Exemple:

strace -e trace=open date

me montre ceci:

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

à partir duquel on pourrait utiliser les noms ".so" pour voir uniquement les objets partagés.

Thomas Dickey
la source
3
Une amélioration:strace -e trace=open,openat myprogram
Cyker
Belle méthode. /proc/<pid>/mapsaffiche également dlopenlibs btw: unix.stackexchange.com/questions/120015/…, la ltrace -S sortie est encore plus froide car elle affiche à la fois les appels système et les appels de bibliothèque tels que dlopen: unix.stackexchange.com/questions/226524/…
Ciro Santilli事件
7

lsof peut également vous montrer quelles bibliothèques sont utilisées pour un processus particulier.

c'est à dire

$ 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
Gongora
la source
2

Pour un processus de pid 1234, vous pouvez également lire le /proc/1234/mapspseudo-fichier (textuel) (read proc (5) ...) ou utiliser pmap (1)

Cela donne l’ espace d’adresse virtuel de ce processus, d’où les fichiers (y compris les bibliothèques partagées, même celles contenant le fichier dlopen (3) ) qui sont mappés en mémoire.

(bien sûr, utilisez ps auxou pgrep (1) pour trouver les processus exécutant un programme donné)

Basile Starynkevitch
la source
1

Pour une requête en masse:

  1. créer un petit script ( useslib) et le mettre dans le PATH (ou spécifier un chemin complet dans la commande ci-dessous)

    #! /bin/bash
    ldd $1 | grep -q $2
    exit $?
    
  2. Utilisez-le dans une findcommande, par exemple:

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

(libgtk-x11-2.0 semble être la lib gtk2)

xénoïde
la source
0

C'est utilisation possible pmap.

Par exemple, démarrez un processus: $ watch date

Obtenez pid: $ ps -ef | grep watch

Afficher la carte mémoire: $ pmap <pid>

Show avec chemin complet: $ 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
Lane Ouyang
la source