Como mostrar todas as bibliotecas compartilhadas usadas pelos executáveis ​​no Linux?

225

Gostaria de saber quais bibliotecas são usadas pelos executáveis ​​no meu sistema. Mais especificamente, gostaria de classificar quais bibliotecas são mais usadas, juntamente com os binários que as utilizam. Como posso fazer isso?

Alan Szlosek
fonte
Você provavelmente não será capaz de obter um número exato se os executáveis ​​o usarem dlopen.
JXH

Respostas:

271
  1. Use lddpara listar bibliotecas compartilhadas para cada executável.
  2. Limpar a saída
  3. Classificar, calcular contagens, classificar por contagem

Para encontrar a resposta para todos os executáveis ​​no diretório "/ bin":

find /bin -type f -perm /a+x -exec ldd {} \; \
| grep so \
| sed -e '/^[^\t]/ d' \
| sed -e 's/\t//' \
| sed -e 's/.*=..//' \
| sed -e 's/ (0.*)//' \
| sort \
| uniq -c \
| sort -n

Altere "/ bin" acima para "/" para pesquisar todos os diretórios.

A saída (apenas para o diretório / bin) será mais ou menos assim:

  1 /lib64/libexpat.so.0
  1 /lib64/libgcc_s.so.1
  1 /lib64/libnsl.so.1
  1 /lib64/libpcre.so.0
  1 /lib64/libproc-3.2.7.so
  1 /usr/lib64/libbeecrypt.so.6
  1 /usr/lib64/libbz2.so.1
  1 /usr/lib64/libelf.so.1
  1 /usr/lib64/libpopt.so.0
  1 /usr/lib64/librpm-4.4.so
  1 /usr/lib64/librpmdb-4.4.so
  1 /usr/lib64/librpmio-4.4.so
  1 /usr/lib64/libsqlite3.so.0
  1 /usr/lib64/libstdc++.so.6
  1 /usr/lib64/libz.so.1
  2 /lib64/libasound.so.2
  2 /lib64/libblkid.so.1
  2 /lib64/libdevmapper.so.1.02
  2 /lib64/libpam_misc.so.0
  2 /lib64/libpam.so.0
  2 /lib64/libuuid.so.1
  3 /lib64/libaudit.so.0
  3 /lib64/libcrypt.so.1
  3 /lib64/libdbus-1.so.3
  4 /lib64/libresolv.so.2
  4 /lib64/libtermcap.so.2
  5 /lib64/libacl.so.1
  5 /lib64/libattr.so.1
  5 /lib64/libcap.so.1
  6 /lib64/librt.so.1
  7 /lib64/libm.so.6
  9 /lib64/libpthread.so.0
 13 /lib64/libselinux.so.1
 13 /lib64/libsepol.so.1
 22 /lib64/libdl.so.2
 83 /lib64/ld-linux-x86-64.so.2
 83 /lib64/libc.so.6

Editar - Removido "grep -P"

John Vasileff
fonte
2
Esta é uma ótima resposta (eu votei para cima), mas você pode explicar o comando "grep -P '\ t. * So'"? De acordo com o man, isso interpreta o padrão como um perex regexp, mas minha versão do grep não o suporta (o man indica que esse é um problema geral). Qual parte do regexp é específica para perl?
Bobby Jack
2
Eu acho que você pode precisar usarldd -v
MountainX
58
Esteja ciente de que lddrealmente executa o executável com uma variável de ambiente especial, e o vinculador dinâmico do Linux reconhece esse sinalizador e apenas gera as bibliotecas em vez de executar o executável. Olhe a fonte para ldd; no meu sistema, é um script bash. Se o executável estiver estaticamente vinculado e usar syscalls e especificar um carregador diferente, ele poderá fazer coisas arbitrárias. Portanto, não use lddem um executável em que não confie.
Barry Kelly
'ldd' não funciona para mim em binários de compilação cruzada. A questão é encontrar as bibliotecas usadas pelos programas no sistema atual (que seriam programas nativos, conforme formulado). Esta é uma boa resposta para isso. No entanto, pensei em mencionar que você precisa usar outra coisa se procurar as bibliotecas compartilhadas por programas para um sistema diferente ('readelf' mencionado em outra resposta, funcionou para mim)
Tim Bird
68

Eu não tinha ldd na minha cadeia de ferramentas do ARM, então usei o objdump:

Objdump de $ (CROSS_COMPILE) -p

Por exemplo:

objdump -p /usr/bin/python:

Dynamic Section:
  NEEDED               libpthread.so.0
  NEEDED               libdl.so.2
  NEEDED               libutil.so.1
  NEEDED               libssl.so.1.0.0
  NEEDED               libcrypto.so.1.0.0
  NEEDED               libz.so.1
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  INIT                 0x0000000000416a98
  FINI                 0x000000000053c058
  GNU_HASH             0x0000000000400298
  STRTAB               0x000000000040c858
  SYMTAB               0x0000000000402aa8
  STRSZ                0x0000000000006cdb
  SYMENT               0x0000000000000018
  DEBUG                0x0000000000000000
  PLTGOT               0x0000000000832fe8
  PLTRELSZ             0x0000000000002688
  PLTREL               0x0000000000000007
  JMPREL               0x0000000000414410
  RELA                 0x0000000000414398
  RELASZ               0x0000000000000078
  RELAENT              0x0000000000000018
  VERNEED              0x0000000000414258
  VERNEEDNUM           0x0000000000000008
  VERSYM               0x0000000000413534
smichak
fonte
2
Isso também deve ser seguro, diferente do lddque não deve ser usado em executáveis ​​não confiáveis.
PSKocik 02/09/19
Além disso, obbjdump -pmostra informações adicionais como o RPATH, que podem ajudar na investigação de problemas de vínculo dinâmico com o seu executável.
Sitaktif
+1 para o método que é realmente seguro e confiável (de alguma forma, eu tenho um sistema em que musl-gccproduz binários regularmente, de forma que a chamada lddno binário apenas executa o binário , então hoje em dia sou regularmente lembrado de quão inseguro lddé).
Mtraceur 11/07/19
54

No Linux eu uso:

lsof -P -T -p Application_PID

Isso funciona melhor do que lddquando o executável usa um carregador não padrão

Fabiano Tarlao
fonte
Usei isso para descobrir se o mariadb estava realmente usando o tc-malloc , que é carregado pelo LD_PRELOAD. Funciona bem.
Cmc #
2
Eu estava procurando por algo que me mostrasse '.so' para um dado pid. Isso é exatamente o que eu precisava. Obrigado!
Leo Ufimtsev
48

para aprender quais bibliotecas um binário usa, use ldd

ldd path/to/the/tool

Você teria que escrever um pequeno script de shell para chegar ao seu colapso em todo o sistema.

pilif
fonte
19

Verificar dependências da biblioteca compartilhada de um programa executável

Para descobrir de quais bibliotecas um determinado executável depende, você pode usar o comando ldd. Este comando chama o vinculador dinâmico para descobrir as dependências da biblioteca de um executável.

> $ ldd / caminho / para / programa

Observe que NÃO é recomendável executar o ldd com nenhum executável de terceiros não confiável, porque algumas versões do ldd podem chamar diretamente o executável para identificar suas dependências da biblioteca, o que pode ser um risco à segurança.

Em vez disso, uma maneira mais segura de mostrar dependências da biblioteca de um aplicativo binário desconhecido é usar o seguinte comando.

$ objdump -p / caminho / para / programa | grep NECESSÁRIO

para mais informações

kayle
fonte
14

readelf -d recursão

redelf -dproduz uma saída semelhante à objdump -pmencionada em: https://stackoverflow.com/a/15520982/895245

Mas lembre-se de que as bibliotecas dinâmicas podem depender de outras bibliotecas dinâmicas, para que você precise recursar.

Exemplo:

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

Saída da amostra:

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

Então:

$ 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

Escolha um e repita:

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

Saída de amostra:

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]

E assim por diante.

/proc/<pid>/maps para processos em execução

Isso é útil para encontrar todas as bibliotecas atualmente sendo usadas executando executáveis. Por exemplo:

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

mostra todas as dependências dinâmicas atualmente carregadas 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 também mostra as bibliotecas abertas com dlopen, testadas com esta configuração mínima hackeada com uma sleep(1000)no Ubuntu 18.04.

Consulte também: /superuser/310199/see-currently-loaded-shared-objects-in-linux/1243089

Ciro Santilli adicionou uma nova foto
fonte
7

No OS X, por padrão, não há ldd, objdumpou lsof. Como alternativa, tente otool -L:

$ otool -L `which openssl`
/usr/bin/openssl:
    /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

Neste exemplo, o uso which opensslpreenche o caminho completo para o ambiente de usuário atual e executável especificado.

bluebadge
fonte
6

No sistema UNIX, suponha que o nome binário (executável) seja test. Em seguida, usamos o seguinte comando para listar as bibliotecas usadas no teste:

ldd test
Raghwendra
fonte
4

Com lddvocê pode obter as bibliotecas que as ferramentas usam. Para classificar o uso de bibliotecas para um conjunto de ferramentas, você pode usar algo como o seguinte comando.

ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c

(Aqui, sedretira todas as linhas que não começam com uma guia e os filtros apenas as bibliotecas reais. Com sort | uniq -cvocê, cada biblioteca recebe uma contagem indicando o número de vezes que ocorreu.)

Você pode adicionar sort -gno final para obter as bibliotecas em ordem de uso.

Observe que você provavelmente obtém linhas duas linhas não pertencentes à biblioteca com o comando acima. Um dos executáveis ​​estáticos ("não é um executável dinâmico") e outro sem nenhuma biblioteca. O último é o resultado do linux-gate.so.1qual não é uma biblioteca no seu sistema de arquivos, mas uma "fornecida" pelo kernel.

Mweerden
fonte
2

Mais uma opção pode ser apenas ler o arquivo localizado em

/proc/<pid>/maps

Por exemplo, se o ID do processo é 2601, o comando é

cat /proc/2601/maps

E a saída é como

7fb37a8f2000-7fb37a8f4000 r-xp 00000000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37a8f4000-7fb37aaf3000 ---p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf3000-7fb37aaf4000 r--p 00001000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf4000-7fb37aaf5000 rw-p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf5000-7fb37aafe000 r-xp 00000000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37aafe000-7fb37acfd000 ---p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfd000-7fb37acfe000 r--p 00008000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfe000-7fb37acff000 rw-p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acff000-7fb37ad1d000 r-xp 00000000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37ad1d000-7fb37af1d000 ---p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1d000-7fb37af1e000 r--p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1e000-7fb37af1f000 rw-p 0001f000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1f000-7fb37af21000 r-xp 00000000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37af21000-7fb37b121000 ---p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b121000-7fb37b122000 r--p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b122000-7fb37b123000 rw-p 00003000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
SoSen
fonte
2

nos pacotes de impressão do ubuntu relacionados a um executável

ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F  ":"  '{print $1}'
Shimon Doodkin
fonte
0

Achei este post muito útil, pois precisava investigar dependências de uma biblioteca fornecida por terceiros (caminho (s) de execução de 32 vs 64 bits).

Eu montei um script bash recorrente de Q&D baseado na sugestão 'readelf -d' em uma distro do RHEL 6.

É muito básico e testará todas as dependências todas as vezes, mesmo que possa ter sido testado antes (isto é, muito detalhado). A saída também é muito básica.

#! /bin/bash

recurse ()
# Param 1 is the nuumber of spaces that the output will be prepended with
# Param 2 full path to library
{
#Use 'readelf -d' to find dependencies
dependencies=$(readelf -d ${2} | grep NEEDED | awk '{ print $5 }' | tr -d '[]')
for d in $dependencies; do
   echo "${1}${d}"
   nm=${d##*/}
   #libstdc++ hack for the '+'-s
   nm1=${nm//"+"/"\+"}
   # /lib /lib64 /usr/lib and /usr/lib are searched
   children=$(locate ${d} | grep -E "(^/(lib|lib64|usr/lib|usr/lib64)/${nm1})")
   rc=$?
   #at least locate... didn't fail
   if [ ${rc} == "0" ] ; then
      #we have at least one dependency
      if [ ${#children[@]} -gt 0 ]; then
         #check the dependeny's dependencies
         for c in $children; do
          recurse "  ${1}" ${c}
         done
      else
         echo "${1}no children found"
      fi
   else
      echo "${1}locate failed for ${d}"
   fi
done
}
# Q&D -- recurse needs 2 params could/should be supplied from cmdline
recurse "" !!full path to library you want to investigate!!

redirecionar a saída para um arquivo e grep para 'encontrado' ou 'falhou'

Use e modifique, por sua conta e risco, é claro, como desejar.

Anders Domeij
fonte