¿Por qué (y cómo) tengo (aparentemente) símbolos duplicados en mis bibliotecas compartidas?

¿Por qué (y cómo) tengo (aparentemente) símbolos duplicados en mis bibliotecas compartidas?

Tuve que averiguar qué símbolos fueron exportados por cada biblioteca de una lista plana de símbolos de biblioteca compartida exportados. Había suficientes símbolos (20 aproximadamente) en la lista como para no hacer una referencia cruzada manual de cada uno.

Descubrí que nm -A -D -f sysv <library-name>parecía producir resultados útiles: podía buscar líneas que contuvieran FUNCeso y que también incluyeran una dirección en la segunda columna. Así que ejecuté este comando en todo el contenido /usr/liby lo redirigí a un archivo.

Para mi sorpresa, la verificación de cordura en el script que hice para analizar el archivo informó que había símbolos duplicados. Al investigar y descubrió que¿Las bibliotecas parecían estar exportando símbolos duplicados?

Verifiqué esto usando algunas secuencias de comandos de Shell y pude convertir los comandos que usé en esto (técnicamente) un trazador de líneas:

readlink -f /lib/* /usr/lib/* \
  | grep -F .so. | sort | uniq \
  | while read x; do nm -A -D -f sysv $x; done \
  | grep FUNC | cut -d'|' -f1 | sort -g | uniq -c | sort -g \
  | sed -n '/^ \+1/!{s/^ \+[0-9]\+ \+//p}' | sed 's/ //g' \
  | tr '\n' '\v' \
  | sed ':1;s/\([^ ]\+\):\([^\v$]\+\)\v\1:/\1:\2|/g;t1' \
  | tr '\v' '\n' \
  | while IFS=: read -a x; do \
     nm -A -D -f sysv "${x[0]}" | grep ":\\(${x[1]//|/\\|}\\).*FUNC"; \
  done

El comando anterior hará que su disco busque por un corto período de tiempo. Puedes dividirlo en partes que redirijan a archivos temporales si lo deseas. Tambiénla salida será muy amplia(~150 cols).

Inicialmente ejecuté el script original en un chroot de Debian Squeeze en el que estaba trabajando, pero por curiosidad ejecuté lo anterior en mi sistema host para descubrir si el chroot de alguna manera no estaba en su sano juicio.

Bueno... el chroot informó poco más de 90 duplicados, pero mi sistema host (Arch) aparentemente tiene alrededor de 267.

El comando funciona mediante grepping nmde la salida, por lo que los resultados son un poco ruidosos, pero se ve así:

/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|00043700|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access|000436c0|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_access_mask|000458f0|   T  |              FUNC|00000058|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|000432a0|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size|00043260|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00044ff0|   T  |              FUNC|0000003c|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_max|00045030|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|000453c0|   T  |              FUNC|00000037|     |.text
/usr/lib/libasound.so.2.0.0:snd_pcm_hw_params_get_buffer_size_min|00045380|   T  |              FUNC|0000003c|     |.text

Observe cómo hay dos de cada símbolo.La dirección es diferente., sí, pero... Pensé que el enlace dinámico funcionaba por nombre de símbolo, y eso era todo. Mi confusión se ve agravada por el hecho de que (si se desplaza hacia la derecha en la lista anterior) todos los símbolos son de tipo FUNCy de la .textsección.

Estoy publicando esto para saber qué magia interesante está sucediendo debajo del capó aquí. (Dado que mi sistema está funcionando...)

Si alguien tiene alguna buena idea sobre dónde podría descargar unas 600 líneas de texto (Pastebin ya no parece estar de moda y no uso GitHub), estaría feliz de compartir el resultado completo.

Respuesta1

Los símbolos aparecen duplicados porque la información proporcionada por nmes incompleta: los símbolos en cuestión están versionados. Puedes ver esto con objdump -T:

0000000000059d00 g    DF .text  0000000000000044 (ALSA_0.9)   snd_pcm_hw_params_get_access
0000000000056040 g    DF .text  000000000000004b  ALSA_0.9.0rc4 snd_pcm_hw_params_get_access

o opción nmde --with-symbol-versions:

/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000059d00|   T  |              FUNC|0000000000000044|     |.text@ALSA_0.9
/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0:snd_pcm_hw_params_get_access|0000000000056040|   T  |              FUNC|000000000000004b|     |.text@@ALSA_0.9.0rc4

Los binarios están vinculados con una versión específica del símbolo y obtendrán la correcta en el momento del vínculo. Esto permite cambiar las API manteniendo la compatibilidad con versiones anteriores.

información relacionada