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?