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?
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?
Respostas:
ldd
para listar bibliotecas compartilhadas para cada executável.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"
ldd -v
ldd
realmente 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 ldd
em um executável em que não confie.
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
ldd
que não deve ser usado em executáveis não confiáveis.
obbjdump -p
mostra informações adicionais como o RPATH
, que podem ajudar na investigação de problemas de vínculo dinâmico com o seu executável.
musl-gcc
produz binários regularmente, de forma que a chamada ldd
no binário apenas executa o binário , então hoje em dia sou regularmente lembrado de quão inseguro ldd
é).
No Linux eu uso:
lsof -P -T -p Application_PID
Isso funciona melhor do que ldd
quando o executável usa um carregador não padrão
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
readelf -d
recursão
redelf -d
produz uma saída semelhante à objdump -p
mencionada 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
No OS X, por padrão, não há ldd
, objdump
ou 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 openssl
preenche o caminho completo para o ambiente de usuário atual e executável especificado.
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
Com ldd
você 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, sed
retira todas as linhas que não começam com uma guia e os filtros apenas as bibliotecas reais. Com sort | uniq -c
você, cada biblioteca recebe uma contagem indicando o número de vezes que ocorreu.)
Você pode adicionar sort -g
no 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.1
qual não é uma biblioteca no seu sistema de arquivos, mas uma "fornecida" pelo kernel.
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
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}'
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.
dlopen
.