Encontre onde está um símbolo de biblioteca compartilhada definido em um sistema ativo / liste todos os símbolos exportados em um sistema

21

Basicamente, são duas perguntas em uma - porque, se eu puder listar todos os símbolos exportados em um sistema, juntamente com o caminho de sua biblioteca compartilhada, poderia simplesmente obter grepessa saída.

Para símbolos do kernel, acho que é um pouco mais fácil - porque sempre podemos cat /proc/kallsymsobter uma lista de todos os símbolos desses módulos carregados na memória; em seguida sudo cat /proc/modules, fornecerá uma lista de módulos carregados com seus endereços, mas não os caminhos de onde os módulos foram carregados (se eles forem criados como objetos .ko separados e fora da árvore)

Por exemplo, tento rastrear o programa kstusando ltrace:

$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
...

... e eu gostaria de saber onde isso _ZNK13QGraphicsItem10parentItemEvreside.

Então, o que fazer com os símbolos da biblioteca compartilhada? Lendo através do [gcc-help] Re: localizando a biblioteca na qual o símbolo está definido. ; Eu tentei algo assim:

$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...

... mas isso me dá problemas adicionais: eu realmente não conheço todos os caminhos que são verificados em busca de bibliotecas compartilhadas no meu sistema; portanto, quando tentei pela primeira vez find /lib ..., não encontrei nada; Acho essa palpite cansativa para diretórios, bem como a alternativa: escanear todo o sistema de arquivos-raiz com find... E também pareço acertar * .sos que não podem ser abertos nm(talvez porque sejam links simbólicos?), Que gerar várias mensagens de erro (das quais também não gosto).

A questão é - ldd(ou ld?) Provavelmente executa algumas dessas pesquisas de símbolos, mas tentei as respectivas páginas de manual e não consigo encontrar uma maneira de "encontrar" qualquer símbolo na linha de comando, sem fornecer algum tipo de arquivo executável como um argumento. Pergunta secundária - haveria uma maneira de usar essas ferramentas para isso?

Então, o que eu estou procurando uma ferramenta de linha de comando, que se comportaria algo como (pseudocódigo):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

... onde eu não especifico nenhum diretório para pesquisar - mas que também manipula, por exemplo, LD_PRELOADou LD_LIBRARY_PATH; diga se eu fizer:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

... então eu pegaria o local /path/to/mylib.soonde o símbolo fornecido foi definido (dado que esse símbolo não existiria nas bibliotecas padrão) - e produziria "não encontrado" caso contrário. Caso contrário, ./findsymbol --dumpallpoderia produzir uma lista de todos os símbolos disponíveis e seus locais vistos em um determinado ambiente (por exemplo, um bashshell específico ).

Existe uma ferramenta como esta para Linux?

sdaau
fonte

Respostas:

16

Os caminhos para procurar bibliotecas serão listados no arquivo /etc/ld.so.conf, na variável de ambiente LD_LIBRARY_PATHe em qualquer RPATHs codificado no binário ELF. O programa lddinformará quais bibliotecas um aplicativo específico carregará.

Depois de ter um símbolo curioso, você pode usar o programa nmpara despejar símbolos .oe .aarquivos e readelfdespejar símbolos de um .soou qualquer elfo executável.

Exemplos:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

E finalmente, com esse cenário de lado, aqui está o seu Santo Graal:

Dado um símbolo _ZN6Kopete6Global10PropertiesC2Ev, onde é isso?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

que produz:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

A -lbandeira diz para procurar dirs /etc/ld.so.confe -sespecifica o símbolo a ser encontrado.

Casey
fonte
Isso está incompleto: alguns programas carregam bibliotecas de diretórios específicos de aplicativos.
Gilles 'SO- stop be evil'
2
O @Gilles scanelfpermite que você especifique diretórios específicos para pesquisar e oferecer suporte à pesquisa recursiva, -rpara que você possa ajustar seus caminhos de pesquisa ou pesquisar em todo o sistema sem muitos problemas. Por exemplo scanelf -r -s SYMBOL /lib/* /usr/* /opt/*, encontrará a maioria dos lugares que as bibliotecas estão escondidas.
quer
7

Nos sistemas GNU (ao usar o vinculador dinâmico GNU libc), você pode executar seu programa como:

LD_DEBUG=bindings kst2

Para descobrir onde os símbolos são resolvidos.

Stéphane Chazelas
fonte
0

Eu já me deparei com isso várias vezes, tentando portar código de um sistema Linux para outro. Normalmente, acabo cumprimentando todos os diretórios padrão. Não consegui encontrar nada no Google. Então, aqui está um script rápido:

edt11x / findinsharedlibs

edt11x
fonte