Localizar onde é um símbolo de biblioteca compartilhada definido em um sistema / lista ao vivo, todos os símbolos exportados em um sistema

19

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

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

Por exemplo, tento rastrear o programa kst usando 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 gostaria de saber onde esse _ZNK13QGraphicsItem10parentItemEv reside.

Então, o que fazer com os símbolos da biblioteca compartilhada? Leitura através de [gcc-help] Re: encontrar 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 varridos para bibliotecas compartilhadas no meu sistema, então quando eu tentei pela primeira vez find /lib ... ele não achou nada; Acho que essa adivinhação de diretórios é irritante, assim como a alternativa: escanear todo o sistema de arquivos raiz com find ... E também, parece que eu acertei * .so que não pode ser aberto por nm (talvez porque eles são symlinks?), que geram um grande número de mensagens de erro (que eu também não gosto).

A coisa é - ldd (ou ld ?) provavelmente realiza algumas dessas pesquisas de símbolos, mas eu 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 argumento. Pergunta secundária - há uma maneira de usar essas ferramentas para isso?

Então, o que estou procurando é uma ferramenta de linha de comando, que se comportaria como algo (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 lida, por exemplo LD_PRELOAD ou LD_LIBRARY_PATH ; diga se eu fizer:

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

... então eu obteria o /path/to/mylib.so onde o símbolo dado estava definido (dado que tal símbolo não existiria nas bibliotecas padrão) - e produziria "not found" caso contrário. E, de outro modo, ./findsymbol --dumpall poderia produzir uma lista de todos os símbolos disponíveis e suas localizações vistas de um determinado ambiente (por exemplo, um específico bash shell).

Existe uma ferramenta como esta para o Linux?

    
por sdaau 04.12.2013 / 23:01

3 respostas

13

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

Uma vez que você tenha um símbolo de que esteja curioso, poderá usar o programa nm para despejar símbolos de .o e .a files e readelf para despejar símbolos de um executável .so ou qualquer elf.

Exemplos:

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

E, finalmente, com esse pano de fundo de lado, aqui está seu Santo Graal:

Dado um símbolo _ZN6Kopete6Global10PropertiesC2Ev , onde está isso?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

que produz:

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

O sinalizador -l diz para pesquisar dirs em /etc/ld.so.conf e o -s especifica o símbolo a ser encontrado.

    
por 04.12.2013 / 23:38
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.

    
por 05.12.2013 / 12:31
0

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

edt11x / findinsharedlibs

    
por 08.05.2016 / 23:03