¿Cómo averiguar las cargas ejecutables de las bibliotecas dinámicas cuando se ejecutan?

64

Quiero encontrar la lista de bibliotecas dinámicas que un binario carga cuando se ejecuta (con sus rutas completas). Estoy usando CentOS 6.0. ¿Como hacer esto?

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente

Respuestas:

61

Puedes hacer esto con el lddcomando:

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

Ejemplo:

$ 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
fuente
1
¿Alguna idea de lo que sería un equivalente macOS de esto? No llden Darwin, parece, ni puedo encontrarlo a través de homebrew.
mz2
77
En macOS:otool -L <path-to-binary>
Richard Viney
Tenga en cuenta que esto puede ejecutar el binario. Entonces, si el binario no es de confianza, puede ser mejor no usarlo ldd. Ver página del manual .
Paul Rooney
46

readelf -d $executable | grep 'NEEDED'

Se puede usar si no puede ejecutar el ejecutable, por ejemplo, si se compiló de forma cruzada o si no confía en él:

En el caso habitual, ldd invoca el vinculador dinámico estándar (consulte ld.so (8)) con la variable de entorno LD_TRACE_LOADED_OBJECTS establecida en 1, lo que hace que el vinculador muestre las dependencias de la biblioteca. Sin embargo, tenga en cuenta que, en algunas circunstancias, algunas versiones de ldd pueden intentar obtener la información de dependencia ejecutando directamente el programa. Por lo tanto, nunca debe emplear ldd en un ejecutable no confiable, ya que esto puede resultar en la ejecución de código arbitrario.

Ejemplo:

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

Muestra de salida:

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

Tenga en cuenta que las bibliotecas pueden depender de otras bibliotecas, por lo que ahora necesita encontrar las dependencias.

Un enfoque ingenuo que a menudo funciona es:

$ 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

pero el método más preciso es comprender la lddruta de búsqueda / caché. Creo que ldconfiges el camino a seguir.

Elija uno y repita:

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

Salida de muestra:

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]

Y así.

Ver también:

/proc/<pid>/maps para ejecutar procesos

Mencionado por Basile , esto es útil para encontrar todas las bibliotecas que se utilizan actualmente ejecutando ejecutables. P.ej:

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

muestra todas las dependencias dinámicas cargadas actualmente de 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

Este método también muestra bibliotecas abiertas con dlopen, probadas con esta configuración mínima pirateada con un sleep(1000)en Ubuntu 18.04.

Consulte también: ¿Cómo ver los objetos compartidos cargados actualmente en Linux? El | Super usuario

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
1
Lo bueno del método readelf es que también funciona en binarios cruzados (ej .: armhf en amd64)
Ghostrider
13

ldd y lsof muestran las bibliotecas cargadas directamente o en un momento dado . No tienen en cuenta las bibliotecas cargadas a través de dlopen(o descartadas pordlclose ). Puede obtener una mejor imagen de esto usando strace, por ejemplo,

strace -e trace=open myprogram

(ya que en dlopenúltima instancia llama open, aunque, por supuesto, puede tener un sistema que use diferentes nombres para las aperturas de 64 bits ...).

Ejemplo:

strace -e trace=open date

me muestra esto:

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

desde el cual se podrían seleccionar los nombres ".so" para ver simplemente los objetos compartidos.

Thomas Dickey
fuente
3
Una mejora:strace -e trace=open,openat myprogram
Cyker
Buen método /proc/<pid>/mapstambién muestra dlopenlibs por cierto: unix.stackexchange.com/questions/120015/… la ltrace -S salida es aún más genial, ya que muestra tanto syscalls como llamadas de biblioteca como dlopen: unix.stackexchange.com/questions/226524/…
Ciro Santilli 新疆 改造 中心 法轮功 六四事件
7

lsof también puede mostrarle qué bibliotecas se están utilizando para un proceso en particular.

es decir

$ 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
Góngora
fuente
2

Para un proceso de pid 1234, también puede leer el /proc/1234/mapspseudo-archivo (textual) (read proc (5) ...) o usar pmap (1)

Esto le da al espacio de direcciones virtuales de ese proceso, por lo tanto, los archivos (incluidas las bibliotecas compartidas, incluso dlopen (3) -ed) que se asignan en memoria

(por supuesto, use ps auxo pgrep (1) para encontrar los procesos que ejecutan algún programa dado)

Basile Starynkevitch
fuente
1

Para consulta masiva:

  1. cree un pequeño script ( useslib) y póngalo en la RUTA (o especifique una ruta completa en el siguiente comando)

    #! /bin/bash
    ldd $1 | grep -q $2
    exit $?
    
  2. Úselo en un findcomando, por ejemplo:

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

(libgtk-x11-2.0 parece ser la lib gtk2)

xenoide
fuente
0

Es posible su uso pmap.

Por ejemplo, inicie un proceso: $ watch date

Obtener pid: $ ps -ef | grep watch

Mostrar mapa de memoria: $ pmap <pid>

Mostrar con ruta completa: $ 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
fuente