Encuentre dónde está un símbolo de biblioteca compartida definido en un sistema en vivo / enumere todos los símbolos exportados en un sistema

21

Básicamente, se trata de dos preguntas en una, porque si puedo enumerar todos los símbolos exportados dentro de un sistema, junto con su ruta de biblioteca compartida, entonces podría simplemente grepesa salida.

Para los símbolos del núcleo, supongo que es algo más fácil, porque siempre podemos cat /proc/kallsymsobtener una lista de todos los símbolos de esos módulos cargados en la memoria; luego sudo cat /proc/modulesdará una lista de los módulos cargados con sus direcciones, pero no las rutas desde donde se han cargado los módulos (si están construidos como objetos .ko fuera del árbol)

Por ejemplo, trato de rastrear el 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
...

... y me gustaría saber dónde _ZNK13QGraphicsItem10parentItemEvreside esto .

Entonces, ¿qué hacer con los símbolos de biblioteca compartida? Lectura a través de [gcc-help] Re: encontrar la biblioteca en la que se define el símbolo. ; Intenté algo como esto:

$ 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
...

... pero eso me da problemas adicionales: realmente no conozco todas las rutas que se analizan en busca de bibliotecas compartidas en mi sistema, así que cuando lo intenté por primera find /lib ...vez no encontré nada; Me resulta molesto esta suposición de directorios, así como la alternativa: escanear todo el sistema de archivos raíz con find... Y también, parece que golpeo * .so's, que no puede abrirse nm(¿tal vez porque son enlaces simbólicos?), Que genera una cantidad considerable de mensajes de error (que tampoco me gustan).

La cuestión es que ldd( ld¿ o ?) Probablemente realiza parte de esta búsqueda de símbolos, pero probé las páginas de manual respectivas y no puedo encontrar una manera de "encontrar" ningún símbolo de la línea de comandos, sin proporcionar algún tipo de archivo ejecutable como argumento. Pregunta secundaria: ¿habría alguna forma de usar estas herramientas para eso?

Entonces, lo que estoy buscando es una herramienta de línea de comandos, que se comportaría de manera similar a (pseudocódigo):

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

... donde no especifico ningún directorio para buscar, pero que también manejaría, por ejemplo, LD_PRELOADo LD_LIBRARY_PATH; decir si lo hago:

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

... luego obtendría el lugar /path/to/mylib.sodonde se definió el símbolo dado (dado que dicho símbolo no existiría en las bibliotecas estándar) y, de lo contrario, generaría "no encontrado". Y de lo contrario, ./findsymbol --dumpallpodría producir una lista de todos los símbolos disponibles y sus ubicaciones vistas desde un entorno determinado (por ejemplo, un bashshell específico ).

¿Existe una herramienta como esta para Linux?

sdaau
fuente

Respuestas:

16

Las rutas para buscar bibliotecas se enumerarán en el archivo /etc/ld.so.conf, la variable de entorno LD_LIBRARY_PATHy cualquier RPATH codificado en el binario ELF. El programa lddle dirá qué bibliotecas cargará una aplicación específica.

Una vez que tenga un símbolo que le interese, puede usar el programa nmpara volcar símbolos de .oy .aarchivos y readelfvolcar símbolos de un .soo cualquier ejecutable elfo.

Ejemplos:

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

Y finalmente, con ese trasfondo aparte, aquí está tu santo grial:

Dado un símbolo _ZN6Kopete6Global10PropertiesC2Ev, ¿dónde está esto?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

cuyos rendimientos:

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

La -lbandera dice que busque directorios /etc/ld.so.confy -sespecifica el símbolo a buscar.

casey
fuente
Esto está incompleto: algunos programas cargan bibliotecas de directorios específicos de la aplicación.
Gilles 'SO- deja de ser malvado'
2
@Gilles le scanelfpermite especificar directorios específicos para buscar y admitir la búsqueda recursiva -rpara que pueda modificar sus rutas de búsqueda o buscar en todo su sistema sin demasiados problemas. Por ejemplo scanelf -r -s SYMBOL /lib/* /usr/* /opt/*, encontrará la mayoría de los lugares donde se esconden las bibliotecas.
casey
7

En los sistemas GNU (cuando se utiliza el enlazador dinámico libc de GNU), puede ejecutar su programa como:

LD_DEBUG=bindings kst2

Para encontrar dónde se resuelven los símbolos.

Stéphane Chazelas
fuente
0

Me he encontrado con esto varias veces, intentando portar código de un sistema Linux a otro. Por lo general, termino grep'ing todos los directorios estándar. No pude encontrar nada buscando en Google. Así que aquí hay un guión rápido:

edt11x / findinsharedlibs

edt11x
fuente