Почему (и как) в моих общих библиотеках (на первый взгляд!) есть дублирующиеся символы?

Почему (и как) в моих общих библиотеках (на первый взгляд!) есть дублирующиеся символы?

Мне как раз нужно было выяснить, какие символы экспортировались какой библиотекой из простого списка экспортированных символов общей библиотеки. В списке было достаточно символов (около 20), так что я не собирался вручную делать перекрестные ссылки на каждый из них.

Я обнаружил, что это, nm -A -D -f sysv <library-name>похоже, дает полезный вывод — я мог искать строки, содержащие FUNCтакже указанный адрес во втором столбце. Поэтому я запустил эту команду для всего в /usr/lib, перенаправив его в файл.

К моему удивлению, проверка работоспособности скрипта, который я сделал для разбора файла, показала, что там были дублирующиеся символы! После расследования было обнаружено, чтобиблиотеки, похоже, экспортируют дублирующиеся символы?!?

Я проверил это с помощью скриптов оболочки и смог превратить использованные мной команды в это (технически) один лайнер:

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

Команда выше заставит ваш диск искать в течение короткого периода времени. Вы можете разбить его на куски, которые перенаправят во временные файлы, если хотите. Такжевыход будет очень широким(~150 столбцов).

Первоначально я запустил оригинальный скрипт в chroot-окружении Debian Squeeze, в котором я работал, но из любопытства я запустил указанный выше сценарий на своей хост-системе, чтобы выяснить, не является ли chroot-окружение каким-либо ненормальным.

Ну... chroot сообщил о чуть более чем 90 дубликатах, но в моей хостовой системе (Arch) их, по-видимому, около 267.

Команда работает путем поиска nmвыходных данных, поэтому результаты немного зашумлены, но выглядят они примерно так:

/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

Обратите внимание, что каждый символ представлен в двух экземплярах.Адрес другой., да, но... Я думал, что динамическое связывание работает по имени символа, и это было так. Мое замешательство усугубляется тем фактом, что (если вы прокрутите вправо в списке выше) все символы имеют тип FUNCи из .textраздела.

Я публикую это, чтобы узнать, какая интересная магия творится здесь под капотом. (Поскольку моя система работает...)

Если у кого-то есть хорошие идеи, куда можно сбросить около 600 строк текста (Pastebin, похоже, уже не в моде, а GitHub я не использую), я с радостью поделюсь полным выводом.

решение1

Символы кажутся дублированными, поскольку информация, предоставленная nmнеполная: рассматриваемые символы версионированы. Вы можете увидеть это с помощью 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

или nmвариант --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

Бинарные файлы связаны с определенной версией символа, и они получат нужную версию во время связывания. Это позволяет изменять API, сохраняя обратную совместимость.

Связанный контент